I have a JSON doc that looks like:
{ "series": [[1,2], [2,3], [3,4]] }
I'd like to parse this into a set of data types:
data Series = Series [DataPoint]
data DataPoint = DataPoint Int Int -- x and y
I'm having lots of problems trying to write the FromJSON
instance for DataPoint.
instance FromJSON DataPoint where
parseJSON (Array a) = ???
I've tried using Lens to destruct the DataPoint record, but it doesn't compile:
case a ^.. values . _Integer of -}
[x,y] -> DataPoint <$> x <*> y
_ -> mzero
That fails with this error (the first two lines I get even absent the lens trickery, just trying to create a DataPoint <$> 1 <*> 2
):
Couldn't match type ‘aeson-0.7.0.6:Data.Aeson.Types.Internal.Parser
Integer’
with ‘Integer’
Expected type: (aeson-0.7.0.6:Data.Aeson.Types.Internal.Parser
Integer
-> Const
(Data.Monoid.Endo
[aeson-0.7.0.6:Data.Aeson.Types.Internal.Parse
(aeson-0.7.0.6:Data.Aeson.Types.Internal.Parser I
-> Value
-> Const
(Data.Monoid.Endo
[aeson-0.7.0.6:Data.Aeson.Types.Internal.Parser
Value
Actual type: (Integer
-> Const
(Data.Monoid.Endo
[aeson-0.7.0.6:Data.Aeson.Types.Internal.Parse
Integer)
-> Value
-> Const
(Data.Monoid.Endo
[aeson-0.7.0.6:Data.Aeson.Types.Internal.Parser
Value
In the second argument of ‘(.)’, namely ‘_Integer’
In the second argument of ‘(^..)’, namely ‘values . _Integer’
Is there a better way to do this?
Does anybody have an example of parsing arrays of values into a more detailed structure?
The trick here is getting the instance for
FromJSON DataPoint
correct, which takes a little bit of matching but isn't too bad. I came up withWhich will fail to parse cleanly if it isn't able to pull two
Int
s out forx
andy
. Then you just have to define the instance forSeries
:Which, again, will cleanly fail if the data is malformed anywhere. To test:
So it looks like it works.
EDIT: As @maxtaldykin has pointed out, you can just take advantage of the
FromJSON a => FromJSON [a]
instance withWhich is greatly simplified from my original answer. Kudos to Max.
Aeson have instance for list, so I think it is not necessary to deal with vectors.