Let's say I have the following JSON values.
{
"fieldName1": 5,
"value1": "Hello"
}
and
{
"fieldName2": 7,
"value1": "Welcome"
}
I have the following type in Haskell.
data Greeting
= Greeting
{
count :: Int,
name :: Text
}
deriving (Generic, Show, Eq)
How do I parse this JSON into Haskell where fieldName1 or fieldName2 values should be parsed as count value?
I tried to solve this by doing something like shown below.
instance FromJSON Greeting where
parseJSON = withObject "Greeting" $ \obj -> do
count1 <- obj .:? "fieldName1"
count2 <- obj .:? "fieldName2"
name <- obj .: "value1"
count <-
case (count1, count2) of
(Just count, Nothing) -> return count
(Nothing, Just count) -> return count
_ -> fail $ Text.unpack "Field missing"
return Greeting {count = count, name = name}
It works but is very cumbersome and if there are more than 2 alternative values, it becomes a lot more complex. Is there any way to solve this in a simpler way?
The
Parsermonad whereparseJSONruns is itself anAlternative, so you can use the alternation(<|>)operator within the parser definition:If multiple "count" fields are present, this will take the first one that parses.
If you want to process field names more programmatically (for example, if you want to accept a single field whose name starts with the prefix
"field"while rejecting cases with multiple matching fields), then note thatois aKeyMapthat can be processed with the functions in theData.Aeson.KeyMapandData.Aeson.Keymodules: