如何为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
相关产品推荐
相关产品推荐

