Aeson:将动态密钥解析为类型字段

Eri*_*ric 4 haskell aeson

假设有一个类似的JSON:

{
  "bob_id" : {
    "name": "bob",
    "age" : 20
  },
  "jack_id" : {
    "name": "jack",
    "age" : 25
  }
}
Run Code Online (Sandbox Code Playgroud)

是否有可能解析它[Person]Person下面定义的?

data Person = Person {
   id   :: Text
  ,name :: Text
  ,age  :: Int
}
Run Code Online (Sandbox Code Playgroud)

mni*_*iip 7

您无法按[Person]字面定义实例,因为aeson已包含实例[a],但您可以创建新类型,并为其提供实例.

Aeson还包括实例FromJSON a => FromJSON (Map Text a),这意味着如果aeson知道如何解析某些东西,它就知道如何解析那个东西的字典.

您可以在dict中定义类似于值的临时数据类型,然后使用Map实例来定义FromJSON PersonList,其中newtype PersonList = PersonList [Person]:

data PersonInfo = PersonInfo { infoName :: Text, infoAge :: Int }

instance FromJSON PersonInfo where
    parseJSON (Object v) = PersonInfo <$> v .: "name" <*> v .: "age"
    parseJSON _ = mzero

data Person = Person { id :: Text, name :: Text, age :: Int }
newtype PersonList = PersonList [Person]

instance FromJSON PersonList where
    parseJSON v = fmap (PersonList . map (\(id, PersonInfo name age) -> Person id name age) . M.toList) $ parseJSON v
Run Code Online (Sandbox Code Playgroud)