You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell使用aeson反序列化键值对JSON时FromJSON实例编写问题

适配顶层键值对映射JSON的解析方案

你已经编写的单个Person类型的FromJSON逻辑完全可以复用,核心点是区分开单个实体的解析逻辑和顶层JSON结构的解析逻辑:FromJSON Person实例只负责解析包含name/job/id三个字段的单个Person对象,不管这个对象出现在数组里、Map值位置还是某个固定字段下,这套逻辑都不需要修改。

首先先修正你原有代码里的笔误:FromJSON实例的类型名首字母需要大写,正确的单个Person解析实例如下:

import Data.Aeson
import Data.Aeson.Types (withObject)
import Data.ByteString.Lazy (ByteString)
import Data.Map (Map)
import qualified Data.Map as M
import qualified Data.ByteString.Lazy as B

data Person = Person
  { name :: String
  , job  :: String
  , id   :: Int
  } deriving Show

-- 单个Person的解析逻辑,无需修改
instance FromJSON Person where
  parseJSON = withObject "Person" $ \obj -> Person
    <$> obj .: "name"
    <*> obj .: "job"
    <*> obj .: "id"

最简方案:直接复用aeson内置的Map解析能力

aeson默认已经为Map String v/HashMap Text v类型实现了FromJSON实例,会自动把JSON对象的所有键值对解析为Map的键值对,值部分会自动调用你写好的Person解析逻辑,不需要额外写任何自定义实例。

  • 如果你需要保留外层的键名(比如Person1/Person2这类标识),直接把解析目标指定为Map String Person即可:
    -- 直接解析为键到Person的映射
    parsePersonMap :: ByteString -> Either String (Map String Person)
    parsePersonMap = eitherDecode
    
  • 如果你不需要保留外层键名,只想拿到所有Person的列表,直接对解析出的Map取元素即可:
    parsePersonList :: ByteString -> Either String [Person]
    parsePersonList bs = M.elems <$> eitherDecode bs
    

可选方案:定义专属顶层类型

如果你希望用独立类型标记这类顶层映射结构,也可以自定义新类型后编写对应的FromJSON实例:

newtype PersonCollection = PersonCollection (Map String Person) deriving Show

instance FromJSON PersonCollection where
  parseJSON = withObject "PersonCollection" $ \topObj ->
    PersonCollection <$> parseJSON (Object topObj)

补充说明:你之前提到的带People数组的JSON结构,本质也是顶层固定结构+内部Person对象的组合,正确解析逻辑同样是先处理顶层结构,再复用单个Person的解析能力,不需要重写Person的解析逻辑:

newtype PeopleListWrapper = PeopleListWrapper [Person] deriving Show
instance FromJSON PeopleListWrapper where
  parseJSON = withObject "PeopleWrapper" $ \obj ->
    PeopleListWrapper <$> obj .: "People"

内容的提问来源于stack exchange,提问作者Kemp Jenning

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 09:12:19