I am having problems writing a FromJSON instance to parse a JSON file containing an array of objects nested within another array of objects. The file is of the form:
[{"family":[{"name":"Jane","age":31,}
,{"name":"Ana","age":15,}]}
,{"family":[{"name":"Julia","age":45}
,{"name":"Chris","age":47}]}]
For that I created two new types:
-- A person
data Person = Person { name :: String
, age :: Int} deriving (Show, Eq)
-- A family is a list of list of Person
newtype Family = Family {unFamily :: [[Person]]} deriving (Show, Eq)
And their instances are these (using XOverloadedStrings, aeson and text):
instance ToJSON Person where
toJSON (Person n a) = object [ "name" .= n
, "age" .= a]
instance FromJSON Person where
parseJSON (Object o) = Person
<$> o .:? "name" .!= ""
<*> o .:? "age" .!= 0
parseJSON _ = mzero
instance ToJSON Family where
toJSON (Family c) = toJSON . map (\v -> object $ ("family",v):[])
$ map toJSON c
I can make some tests like (with bytestring and maybe loaded)
> julia = Person "Julia" 45
> (== julia) . fromMaybe (Person "" 0) . decode . encode $ julia
True
> BS.putStrLn . BL.toStrict . encode $ Family [[julia,julia],[julia]]
[{"family":[{"age":45,"name":"Julia"},{"age":45,"name":"Julia"}]},{"family":[{"age":45,"name":"Julia"}]}]
and everything works as I wanted. But as I said, I couldn't write FromJSON Family, so I can't test like decode . encode as I did to julia.
I looked at the many types involved in aeson trying to find a way to make it work, but I simply couldn't do it. I could at least write toJSON for ToJSON Family because I learned that type Pair = (Text, Value).
Can anyone point me in a direction here? And is there a better way to write ToJSON Family?