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

使用Aeson解析JSON对象数组时跳过指定项的实现方法

解决JSON数组解析时跳过指定元素的问题

你的核心问题在于:原代码中使用mapM parseJSON arr时,只要数组内有一个元素解析失败(遇到exclude: true触发mzero),整个Response的解析就会直接失败,而非跳过该元素。要实现跳过逻辑,需要在Response的解析层将单个元素的解析结果转为Maybe类型,过滤掉失败的Nothing项即可。

下面提供两种可行的实现方案:

方案1:使用optional在Parser Monad内处理

利用Control.Applicative中的optional函数,将单个元素的解析结果从Parser Foo转为Parser (Maybe Foo)——解析失败时返回Nothing,成功时返回Just Foo,最后过滤掉Nothing得到有效列表。

import Data.Aeson (FromJSON(..), withArray, withObject, (.))
import Data.Text (Text)
import Control.Applicative (optional)
import Data.Maybe (catMaybes)

newtype Response = Response [Foo]
newtype Foo = Foo Text

instance FromJSON Response where
  parseJSON = withArray "Foos" $ \arr -> do
    -- 将每个元素的解析结果转为Maybe,失败则为Nothing
    maybeFoos <- traverse (optional . parseJSON) arr
    -- 过滤掉Nothing,保留有效Foo
    pure $ Response (catMaybes (toList maybeFoos))

instance FromJSON Foo where
  parseJSON = withObject "Foo" $ \foo -> do
    isExcluded <- foo .: "exclude"
    if isExcluded
      then mzero  -- 标记为失败
      else pure $ Foo "bar"

方案2:使用parseMaybe纯函数处理

直接用Data.Aeson提供的parseMaybe函数,将数组中的每个Value直接转为Maybe Foo,再过滤掉Nothing项。

import Data.Aeson (FromJSON(..), withArray, withObject, (.:), parseMaybe)
import Data.Text (Text)
import Data.Maybe (catMaybes)

newtype Response = Response [Foo]
newtype Foo = Foo Text

instance FromJSON Response where
  parseJSON = withArray "Foos" $ \arr -> do
    -- 逐个尝试解析元素,失败得到Nothing
    let maybeFoos = map (parseMaybe parseJSON) (toList arr)
    -- 过滤无效项,构建Response
    pure $ Response (catMaybes maybeFoos)

instance FromJSON Foo where
  parseJSON = withObject "Foo" $ \foo -> do
    isExcluded <- foo .: "exclude"
    if isExcluded
      then mzero
      else pure $ Foo "bar"

两种方案都能实现你的需求:跳过所有带有exclude: true的对象,只保留有效解析的Foo元素。区别在于optional是在Parser Monad内部处理失败逻辑,而parseMaybe是通过纯函数直接转换结果,可根据代码风格偏好选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 06:35:32