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

如何使用Thoth.Json.Net根据type属性对JSON数组对象做条件解析

Thoth.Json.Net 基于type字段选择解码器实现方案

核心实现思路

你可以通过Decode.field先取出type字段的值,再用Decode.andThen根据值匹配对应的解码器,最终所有解码器返回同一个可辨识联合类型即可统一处理数组元素。

基础实现步骤

  1. 首先定义对应不同JSON对象类型的可辨识联合,例如:
type MyJsonElement =
    | TypeA of TypeAData
    | TypeB of TypeBData
    | TypeC of TypeCData
  1. 为每个子类型实现对应的解码器:
let typeADecoder = Decode.map TypeA <| Decode.object (fun get ->
    // 按TypeA的结构读取字段
    { Id = get.Required.Field "id" Decode.int
      Name = get.Required.Field "name" Decode.string })

let typeBDecoder = Decode.map TypeB <| Decode.object (fun get ->
    // 按TypeB的结构读取字段
    { Id = get.Required.Field "id" Decode.int
      Value = get.Required.Field "value" Decode.float })
  1. 实现按type字段匹配的统一解码器:
let elementDecoder =
    Decode.field "type" Decode.string
    |> Decode.andThen (function
        | "typeA" -> typeADecoder
        | "typeB" -> typeBDecoder
        | other -> Decode.fail $"未知的元素类型: {other}")
  1. 解析数组时直接使用该统一解码器即可:
let rootDecoder = Decode.field "arrayField" (Decode.list elementDecoder)

提问者更新的优化方案

我在最初的临时方案跑通之后,重新尝试使用计算表达式(CE)和decodeByType自定义解码器,按照@tranquillity提到的方案让每个解码器返回一个可辨识联合类型的值。理清所有类型关系后,我仅需要为Builder指定类型即可,代码如下:

type DecoderBuilder () = 
    member __.Bind((decoder:Decoder<'a>), (func:('a -> Decoder<'b>))) = 
      Decode.andThen func decoder

这样就可以像@brianberns描述的那样,使用CE轻松组合多个解码器。我为自定义解码器和可辨识联合新建了单独的文件,实现了更贴合领域模型的JSON值提取逻辑——如果JSON结构无效就会直接返回错误,从根本上避免了不可表示状态的出现。

整体代码更简洁,函数式风格更显著,也更优雅,感谢大家的帮助。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 17:36:04