Я хочу проанализировать следующее json:
{
"defaults": {
"align": "left"
},
"animals": [
{
"kind": "cat",
"name": "Oscar",
"align": "center"
},
{
"kind": "dog",
"name": "Max"
}
]
}
Parse align:
data Align = Left | Center | Right
instance FromJSON Align where
parseJSON (String "left") = pure Left
parseJSON (String "center") = pure Center
parseJSON (String "right") = pure Right
parseJSON _ = fail "Expect one of [left, center, right]."
Parse default:
data BlockDefaults = BlockDefaults { align :: Align }
-- default value Center if key does not exist
blockDefaults :: BlockDefaults
blockDefaults = BlockDefaults { align = Center }
instance FromJSON BlockDefaults where
parseJSON = withObject "defaults" $ \o -> BlockDefaults <$> o .:? "align" .!= align blockDefaults
Теперь я хочу разбирать собаку и кошку. Если align
не существует (как в dog
), оно должно принимать значение из значений по умолчанию (left
). Так что dog
должно стать Dog{name="Max", align=Center}
и cat
Cat{name="Oscar", align=Left}
.
Но как мне получить доступ к значению выравнивания по умолчанию в parseJSON
?
-- pseudo parse code
instance FromJSON Animal where
parseJSON = withObject "animal" $ \o ->
Animal <$>
o .: "kind" <*>
o .: "name" <*>
o .:? "align" .!= <DefaultValue> -- How to access value from defaults object?
Я не хочу снова проанализировать значения по умолчанию для каждого животного, так как я могу получить доступ к значениям по умолчанию, проанализированным ранее? Предположим, что в defaults
и других animals
.
гораздо больше значений. Итак, код анализатора животных теперь выглядит следующим образом:
parseAnimal :: BlockDefaults -> Value -> Parser Animal
parseAnimal defaults = withObject "animal" $ \o ->
Animal <$>
o .: "kind" <*>
o .: "name" <*>
(
BlockDefaults <$>
o .:? "align" .!= align defaults
)