我有一个案例类,其中包含类型Map[String, String]
完整的类定义为-
case class MyConfig(version: Int, pairs: Map[String, String])
。
我要解码的json是-
{
"version":1,
"pairs":[
{
"key1":"value1",
"key2":"value2"
}
]
}
当我尝试将字符串解码为MyConfig对象println(decode[MyConfig](jsonStr))
时,出现以下错误-
Left(DecodingFailure([K, V]Map[K, V], List(DownField(pairs))))
。
完整的代码是-
case class MyConfig(version: Int, pairs: Map[String, String])
import io.circe._, io.circe.generic.auto._, io.circe.parser._, io.circe.syntax._
val jsonStr = """ {
| "version":1,
| "pairs":[
| {
| "key1":"value1",
| "key2":"value2"
| }
| ]
| } """.stripMargin
println(jsonStr)
println(decode[MyConfig](jsonStr))
我能够解码here所示的Map json对象,但不能解码带有map字段的对象。
您知道如何解决此错误吗?
答案 0 :(得分:3)
问题在于,通用派生的解码器将尝试将"pairs"
的值解析为Map[String, String]
,这意味着它将查找JSON对象,而您拥有的是对象的JSON数组
如果您坚持使用MyConfig
定义和形状类似的输入,则最好编写自己的解码器,而不用io.circe.generic.auto
派生解码器。使用forProductN
这很简单:
case class MyConfig(version: Int, pairs: Map[String, String])
import io.circe.Decoder
implicit val decodeMyConfig: Decoder[MyConfig] =
Decoder.forProduct2[MyConfig, Int, List[Map[String, String]]](
"version",
"pairs"
) {
case (v, ps) => MyConfig(v, ps.flatten.toMap)
}
然后,假设您已如上所述定义jsonStr
:
scala> import io.circe.parser.decode
import io.circe.parser.decode
scala> decode[MyConfig](jsonStr)
res0: Either[io.circe.Error,MyConfig] = Right(MyConfig(1,Map(key1 -> value1, key2 -> value2)))
或者,您可以更改MyConfig
以使pairs
成员为List[Map[String, String]]
,也可以更改JSON模式(或生成它的任何代码)以省略JSON数组层。