如何使用Aeson解析器提取合并JSON对象所有数组值为单个数组
实现方案
核心思路
- 先将JSON输入解析为Aeson的
Object类型(键值对Map结构),自动忽略所有未知键名 - 提取
Object中所有的Value值 - 将每个Value统一解析为指定元素类型的数组
- 拼接所有数组得到最终结果
完整代码示例
{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-} import Data.Aeson (FromJSON(..), Value, withObject, eitherDecode) import Data.Aeson.Types (Parser) import qualified Data.ByteString.Lazy.Char8 as BSL import qualified Data.HashMap.Strict as HM import Data.Foldable (toList) -- 自定义解析函数:接收JSON Value,返回拼接后的数组 concatObjectArrays :: FromJSON a => Value -> Parser [a] concatObjectArrays = withObject "array-containing object" $ \obj -> -- 遍历所有值解析为数组,再拼接 fmap concat $ traverse parseJSON $ toList $ HM.elems obj -- 可选:封装为自定义类型的FromJSON实例,方便直接调用 newtype MergedArray a = MergedArray { getMerged :: [a] } deriving (Show, Eq) instance FromJSON a => FromJSON (MergedArray a) where parseJSON = fmap MergedArray . concatObjectArrays -- 测试用例 main :: IO () main = do let testInput = BSL.pack "{ \"a\": [1,2,3], \"f\": [4,5,6], \"b\": [7,8,9]}" let result = eitherDecode testInput :: Either String (MergedArray Int) print $ fmap getMerged result -- 输出结果:Right [1,2,3,4,5,6,7,8,9]
补充说明
- 你可以直接使用
concatObjectArrays函数作为其他复杂解析逻辑的组成部分,也可以通过MergedArray封装类型直接对整个JSON做解析 - 数组元素类型支持任意实现了
FromJSON的类型,替换代码中的Int为你需要的类型即可 - 如果某个键对应的值不是数组,解析会自动返回错误,符合所有键取值均为数组的预设条件
内容的提问来源于stack exchange,提问作者Marius Melzer
相关产品推荐
相关产品推荐

