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

如何为jsoniter中Map的键自定义序列化?

解决jsoniter-scala中Map键类型的自定义编解码问题

针对你的场景,只需为TreeStatisticOperation实现**KeyCodec**(jsoniter-scala专门用于Map键的编解码器),就能让自动生成的ApiTreeNode编解码器正确处理statistics字段的Map键,无需手动编写整个类的编解码逻辑。

步骤1:实现TreeStatisticOperation的KeyCodec

因为TreeStatisticOperation是密封特质,我们可以通过匹配所有子类,定义它与字符串之间的转换规则:

import com.github.plokhotnyuk.jsoniter_scala.core._
import com.github.plokhotnyuk.jsoniter_scala.macros._

// 假设你已定义AreaId、IconSource及TreeStatisticOperation的子类
case class AreaId(value: String)
case class IconSource(value: String)

case class IconReference(area: AreaId, source: IconSource, id: String)

sealed trait TreeStatisticOperation {
  def id: String
}

// 示例子类,根据你的实际业务调整
case object Count extends TreeStatisticOperation { override val id = "count" }
case object Sum extends TreeStatisticOperation { override val id = "sum" }
case class Average extends TreeStatisticOperation { override val id = "average" }

// 自定义Map键的编解码器
implicit val treeStatisticOperationKeyCodec: KeyCodec[TreeStatisticOperation] = new KeyCodec[TreeStatisticOperation] {
  // 将TreeStatisticOperation编码为JSON字符串键
  override def encodeKey(op: TreeStatisticOperation): String = op.id

  // 从JSON字符串键解码回TreeStatisticOperation实例
  override def decodeKey(key: String, default: TreeStatisticOperation): TreeStatisticOperation = {
    key match {
      case Count.id => Count
      case Sum.id => Sum
      case Average.id => Average
      case _ => throw new DecodingException(s"未知的TreeStatisticOperation类型: $key")
    }
  }
}

步骤2:自动生成ApiTreeNode的编解码器

在TreeStatisticOperation的KeyCodec隐式可用的前提下,直接用JsonCodecMaker生成ApiTreeNode的编解码器即可——它会自动复用你定义的键编解码器:

case class ApiTreeNode(
    value: String,
    label: String,
    field: String,
    path: List[Int],
    icon: Option[IconReference],
    statistics: Map[TreeStatisticOperation, Option[Double]],
  )

// 自动生成完整编解码器,无需手动处理其他字段
implicit val apiTreeNodeCodec: JsonValueCodec[ApiTreeNode] = JsonCodecMaker.make(CodecMakerConfig())

处理带参数的子类(可选)

如果TreeStatisticOperation的子类是带参数的case class(比如需要更多标识信息),只需调整编码/解码逻辑,确保字符串键唯一即可:

// 带参数的子类示例
case class CustomOp(id: String, param: Int) extends TreeStatisticOperation

// 更新KeyCodec逻辑
implicit val treeStatisticOperationKeyCodec: KeyCodec[TreeStatisticOperation] = new KeyCodec[TreeStatisticOperation] {
  override def encodeKey(op: TreeStatisticOperation): String = op match {
    case CustomOp(id, p) => s"$id:$p"
    case other => other.id
  }

  override def decodeKey(key: String, default: TreeStatisticOperation): TreeStatisticOperation = {
    key.split(":", 2) match {
      case Array(id, pStr) => CustomOp(id, pStr.toInt)
      case Array(id) => id match {
        case Count.id => Count
        case Sum.id => Sum
        case _ => throw new DecodingException(s"未知的TreeStatisticOperation类型: $key")
      }
    }
  }
}

内容的提问来源于stack exchange,提问作者david.perez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 04:33:19