I have a JSON object that has a lot of keys that I don't know and lists as values that I would like to have concatenated to one large list.
Example JSON:
{ "a": [1,2,3], "f": [4,5,6], "b": [7,8,9]}
How do I write an Aeson parser that returns [1,2,3,4,5,6,7,8,9]
when applied?
Jeff Happily above mentioned that Map String [Int]
decodes to this format, and so it does!
Prelude> :m +Data.Aeson
Prelude Data.Aeson> :type encode
encode :: ToJSON a => a -> Data.ByteString.Lazy.Internal.ByteString
Prelude Data.Aeson> :m +Data.Map
Prelude Data.Aeson Data.Map> let bs = encode (fromList [("a", [1,2,3]), ("f", [4,5,6]), ("b", [7,8,9])])
Prelude Data.Aeson Data.Map> bs
"{\"a\":[1,2,3],\"b\":[7,8,9],\"f\":[4,5,6]}"
Prelude Data.Aeson Data.Map> decode bs :: Maybe (Map String [Int])
Just (fromList [("a",[1,2,3]),("b",[7,8,9]),("f",[4,5,6])])
Prelude Data.Aeson Data.Map> fmap elems (decode bs :: Maybe (Map String [Int]))
Just [[1,2,3],[7,8,9],[4,5,6]]
Prelude Data.Aeson Data.Map> fmap (mconcat . elems) (decode bs :: Maybe (Map String [Int]))
Just [1,2,3,7,8,9,4,5,6]
(Note that the map elements are not ordered, so the input order is not preserved. An association list [(String, [Int])]
should work better.