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

如何在PureScript中使用Argonaut实现异构类型数组的JSON编解码

Argonaut 异构类型数组编解码实现方案

Argonaut 没有原生的异构数组自动编解码支持,你可以通过自定义总和类型+自定义编解码规则的方式实现需求,以下是完整实现步骤:


步骤1:定义异构元素适配类型

首先定义可以覆盖数组内所有元素类型的总和类型,用于承载异构数据:

-- 适配数组可能出现的所有元素类型:数值/字符串
data HeteroItem = NumItem Number | StrItem String

-- 按需推导通用实例
derive instance eqHeteroItem :: Eq HeteroItem
derive instance showHeteroItem :: Show HeteroItem

如果你的异构数组是固定长度、固定类型顺序的场景(比如示例中固定第一个是数值、第二个是字符串),可以跳过定义总和类型,直接在结构体编解码规则里做强校验,实现更简单。


步骤2:实现解码逻辑(DecodeJson 实例)

任意长度异构数组解码

自定义解码规则,按优先级尝试匹配元素类型,匹配失败返回解码错误:

import Data.Argonaut.Decode (class DecodeJson, decodeJson, (<?>))
import Data.Alt ((<|>))

instance decodeJsonHeteroItem :: DecodeJson HeteroItem where
  decodeJson json = 
    (NumItem <$> decodeJson json)
    <|> (StrItem <$> decodeJson json)
    <?> "expected number or string type"

固定顺序异构数组解码

如果你的数组固定为「数值+字符串」的二元结构,可以直接在父结构体的解码规则里做强校验,不需要单独定义总和类型:

import Data.Argonaut.Decode (class DecodeJson, withObject, (.:), fail)
import Data.Array (index, length)

-- 业务结构体定义
type MyStruct = {
  field :: { numVal :: Number, strVal :: String }
}

instance decodeJsonMyStruct :: DecodeJson MyStruct where
  decodeJson = withObject "MyStruct" \obj -> do
    arr <- obj .: "field"
    if length arr /= 2 
      then fail "field must be an array with exactly 2 elements"
      else do
        num <- decodeJson =<< index arr 0
        str <- decodeJson =<< index arr 1
        pure { field: { numVal: num, strVal: str } }

步骤3:实现编码逻辑(EncodeJson 实例)

任意长度异构数组编码

根据类型分支编码为对应JSON类型即可:

import Data.Argonaut.Encode (class EncodeJson, encodeJson)

instance encodeJsonHeteroItem :: EncodeJson HeteroItem where
  encodeJson (NumItem n) = encodeJson n
  encodeJson (StrItem s) = encodeJson s

固定顺序异构数组编码

对应固定顺序的二元数组场景,编码逻辑如下:

import Data.Argonaut.Encode (class EncodeJson, object, (:=))

instance encodeJsonMyStruct :: EncodeJson MyStruct where
  encodeJson struct = object
    [ "field" := [ encodeJson struct.field.numVal, encodeJson struct.field.strVal ]
    ]

效果验证

-- 任意长度异构数组编解码测试
testArr :: Array HeteroItem
testArr = [NumItem 3.0, StrItem "text"]
encodedArr = encodeJson testArr -- 输出JSON: [3,"text"]
decodedArr = decodeJson (encodeJson testArr) :: Either _ (Array HeteroItem)
-- 输出: Right [NumItem 3.0, StrItem "text"]

-- 固定顺序异构数组编解码测试
testStruct :: MyStruct
testStruct = { field: { numVal: 3.0, strVal: "text" } }
encodedStruct = encodeJson testStruct -- 输出JSON: {"field":[3,"text"]}
decodedStruct = decodeJson (encodeJson testStruct) :: Either _ MyStruct
-- 输出: Right { field: { numVal: 3.0, strVal: "text" } }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 10:06:03