无法使用 circe 解码字段类型为 Map[String, String] 的对象
couldn't decode Object with field Type Map[String, String] using circe
我有一个案例 class,其中包含 Map[String, String]
类型的字段
完整的class定义是-
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))
我能够解码 Map json 对象,如演示的那样 here 但不能解码带有 map 字段的对象。
知道如何解决这个错误吗?
问题在于,一般派生的解码器会尝试将 "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 数组层。
我有一个案例 class,其中包含 Map[String, String]
完整的class定义是-
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))
我能够解码 Map json 对象,如演示的那样 here 但不能解码带有 map 字段的对象。
知道如何解决这个错误吗?
问题在于,一般派生的解码器会尝试将 "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 数组层。