无法使用circe解码字段类型为Map [String,String]的对象

时间:2019-01-04 17:53:56

标签: json scala scala-cats circe

我有一个案例类,其中包含类型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字段的对象。

您知道如何解决此错误吗?

1 个答案:

答案 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数组层。