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

