1

I would like to parse the values of a json object to a list.

Here's my current approach (simplified and the newtype is based on the results of: Aeson: derive some (but not all) fields of a struct (means I need it)):

Json:

{"v1": 1, "v2": 2}

Wanted result:

Test [1,2]

Current approach:

import Data.Aeson
import Data.HashMap.Strict (elems)

newtype Test = Test [Int]
instance FromJSON Test where
  parseJSON (Object o) =
    mapM parseJSON (elems o)

Compilation error:

• Couldn't match type ‘[b0]’ with ‘Test’
  Expected type: aeson-1.1.2.0:Data.Aeson.Types.Internal.Parser Test
    Actual type: aeson-1.1.2.0:Data.Aeson.Types.Internal.Parser [b0]
• In the expression: mapM parseJSON (elems o)
Marius Melzer
  • 863
  • 1
  • 7
  • 10

1 Answers1

4

mapM parseJSON (elems o) returns Parser [Int], but you need Parser (Test [Int]), so the correct way to do that is:

instance FromJSON Test where
    parseJSON (Object o) = Test <$> mapM parseJSON (elems o)

However, the type of argument of parseJSON is Value, the value of argument may not be Object, it can also be an Array, String or etc, so it is better to use withObject to check what is it as:

instance FromJSON Test where
    parseJSON val = withObject "Test" 
                               (\o -> Test <$> mapM parseJSON (elems o))
                               val

withObject will print a meaningful error message when the value of type Value is not Object.

assembly.jc
  • 2,056
  • 1
  • 7
  • 16