Search code examples
haskellaeson

Extract and merge objects values in Aeson parsers


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?


Solution

  • 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.