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

Circe解析JSON至Scala Case Class失败:适配结构的Case Class选型及Map解码器推导咨询

解决Circe解析JSON到Scala Case Class失败的问题

嘿,我来帮你搞定这个解析失败的问题~

首先得明确问题出在哪:你的JSON结构是以产品名称(比如product1、product2)为键,对应每个产品的Detail数据为值的对象,但你定义的Product类是包含code和detail的结构——JSON里根本没有code这个字段,而是键本身就是产品编码,这就导致Circe的自动解码器找不到匹配的结构,自然返回Left结果。

下面给你两种最适配的解决方案:

方案1:直接解析成Map[String, Detail](最推荐)

Circe可以自动推导Map[String, Detail]类型的解码器,因为你的JSON对象本质就是标准的键值对,刚好和Scala的Map对应。代码示例:

import io.circe._, io.circe.generic.auto._, io.circe.parser._

// 只需要保留Detail类,不需要Product类(或者按需保留)
case class Detail(data1: List[Int], data2: List[Int])

// 你的JSON字符串
val jsonStr = """{ "product1" : { "data1" : [0,0,0], "data2" : [0,0,0] }, "product2" : { "data1" : [1,1,1], "data2" : [1,1,1] } }"""

// 直接解码成Map[String, Detail]
decode[Map[String, Detail]](jsonStr) match {
  case Right(productMap) => 
    // 这里得到的是键为产品编码、值为Detail的Map
    productMap.foreach { case (code, detail) => 
      println(s"产品:$code,data1:${detail.data1},data2:${detail.data2}")
    }
  case Left(error) => println(s"解码失败:${error.getMessage}")
}

这种方法完全利用Circe的自动推导能力,不需要写任何自定义解码器,简单高效。

方案2:解析成List[Product](如果需要Product结构)

如果你确实需要把数据转换成Product(code: String, detail: Detail)的结构,可以先解码成Map,再转换成List[Product],或者自定义解码器直接完成转换:

方法A:Map转List[Product]

case class Product(code: String, detail: Detail)

// 先解码成Map,再映射成Product列表
val result = decode[Map[String, Detail]](jsonStr).map { productMap =>
  productMap.map { case (code, detail) => Product(code, detail) }.toList
}

result match {
  case Right(products) => products.foreach(println)
  case Left(error) => println(s"解码失败:${error.getMessage}")
}

方法B:自定义解码器直接解码成List[Product]

implicit val productListDecoder: Decoder[List[Product]] = Decoder.instance { cursor =>
  // 先把JSON对象解析成Map,再转换成Product列表
  cursor.as[Map[String, Detail]].map(_.map { case (code, detail) => Product(code, detail) }.toList)
}

// 直接解码成List[Product]
decode[List[Product]](jsonStr) match {
  case Right(products) => products.foreach(println)
  case Left(error) => println(s"解码失败:${error.getMessage}")
}

总结

  • 如果只是需要快速获取产品编码和对应的Detail数据,方案1的Map[String, Detail]是最贴合你JSON结构的选择,零额外代码。
  • 如果业务逻辑必须用Product类,方案2的两种方式都能轻松实现转换。

内容的提问来源于stack exchange,提问作者Freyr Van Aesir

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 01:49:08