【问题标题】:couldn't decode Object with field Type Map[String, String] using circe无法使用 circe 解码具有字段类型 Map[String, String] 的对象
【发布时间】:2019-05-31 07:34:33
【问题描述】:

我有一个包含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))

我可以解码 Map json 对象,如 here 演示的那样,但不能解码带有 map 字段的对象。

知道如何解决这个错误吗?

【问题讨论】:

    标签: json scala scala-cats circe


    【解决方案1】:

    问题在于,一般派生的解码器会尝试将 "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 数组层。

    【讨论】:

      猜你喜欢
      • 2019-03-15
      • 2020-10-28
      • 2018-12-24
      • 1970-01-01
      • 2020-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-22
      相关资源
      最近更新 更多