Let's say there is a JSON like:
{
"bob_id" : {
"name": "bob",
"age" : 20
},
"jack_id" : {
"name": "jack",
"age" : 25
}
}
Is it possible to parse it to [Person]
with Person
defined like below?
data Person = Person {
id :: Text
,name :: Text
,age :: Int
}
You cannot define an instance for [Person]
literally, because aeson already includes an instance for [a]
, however you can create a newtype, and provide an instance for that.
Aeson also includes the instance FromJSON a => FromJSON (Map Text a)
, which means if aeson knows how to parse something, it knows how to parse a dict of that something.
You can define a temporary datatype resembling a value in the dict, then use the Map instance to define FromJSON PersonList
, where newtype PersonList = PersonList [Person]
:
data PersonInfo = PersonInfo { infoName :: Text, infoAge :: Int }
instance FromJSON PersonInfo where
parseJSON (Object v) = PersonInfo <$> v .: "name" <*> v .: "age"
parseJSON _ = mzero
data Person = Person { id :: Text, name :: Text, age :: Int }
newtype PersonList = PersonList [Person]
instance FromJSON PersonList where
parseJSON v = fmap (PersonList . map (\(id, PersonInfo name age) -> Person id name age) . M.toList) $ parseJSON v
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With