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

如何为含可变名称字段的KeyValueRow类编写Circe解码器

为带动态字段的case class编写Circe解码器

嘿,这个场景我之前也碰到过——咱们的case class KeyValueRow(count: Int, key: String)结构固定,但对应的JSON里除了固定的count字段,另一个字段的键是动态变化的(比如示例里的url、city)。要给这个类写Circe解码器,其实利用Circe对JSON AST的灵活操作就能搞定,下面一步步来实现:

核心思路

我们需要从JSON里提取两个关键信息:

  • 固定的count整数值
  • 除count外唯一的那个字段的键名(也就是KeyValueRow里的key字段值)

Circe的Decoder允许我们直接操作JSON对象,所以我们可以先解析出count,再筛选出剩下的动态字段。

具体实现步骤

1. 先导入必要的Circe包

首先得把Circe的核心类和语法糖导入进来:

import io.circe._
import io.circe.generic.semiauto._

2. 编写自定义Decoder

我们手动实现Decoder[KeyValueRow],逻辑很清晰:

implicit val keyValueRowDecoder: Decoder[KeyValueRow] = Decoder.instance { c =>
  for {
    // 先解析固定的count字段
    count <- c.get[Int]("count")
    // 把当前JSON转成JsonObject,过滤掉count字段
    remainingFields <- c.as[JsonObject].map(_.filterKeys(_ != "count"))
    // 确保剩下的字段只有一个,然后提取它的键名
    (dynamicKey, _) <- remainingFields.headOption match {
      case Some((k, _)) => Right((k, ()))
      case None => Left(DecodingFailure("JSON缺少动态字段(除count外无其他字段)", c.history))
    }
  } yield KeyValueRow(count, dynamicKey)
}

3. 可选:获取动态字段的值

如果你的业务需要同时拿到动态字段的对应值,可以调整代码逻辑,比如:

// 假设我们把case class改成:case class KeyValueRow(count: Int, key: String, value: String)
implicit val keyValueRowDecoder: Decoder[KeyValueRow] = Decoder.instance { c =>
  for {
    count <- c.get[Int]("count")
    remainingFields <- c.as[JsonObject].map(_.filterKeys(_ != "count"))
    (dynamicKey, dynamicValue) <- remainingFields.headOption match {
      case Some((k, v)) => v.as[String].map(vStr => (k, vStr))
      case None => Left(DecodingFailure("JSON缺少动态字段", c.history))
    }
  } yield KeyValueRow(count, dynamicKey, dynamicValue)
}

4. 测试验证

用你给出的示例JSON来测试一下:

// 测试url场景
val jsonUrl = """{"count":974989,"url":"http://google.com"}"""
io.circe.parser.decode[KeyValueRow](jsonUrl) 
// 输出:Right(KeyValueRow(974989, "url"))

// 测试city场景
val jsonCity = """{"count":1234,"city":"Rome"}"""
io.circe.parser.decode[KeyValueRow](jsonCity)
// 输出:Right(KeyValueRow(1234, "city"))

如果JSON里除了count存在多个动态字段,解码器会返回Left,你也可以根据业务需求调整这部分逻辑(比如抛出更明确的错误,或者默认取第一个字段)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:15:45