I have an case class which contains field of type Map[String, String]
The complete class definition is -
case class MyConfig(version: Int, pairs: Map[String, String])
.
The json I'm trying to decode is -
{
"version":1,
"pairs":[
{
"key1":"value1",
"key2":"value2"
}
]
}
When I try to decode the string into MyConfig object println(decode[MyConfig](jsonStr))
I get the below error -
Left(DecodingFailure([K, V]Map[K, V], List(DownField(pairs))))
.
The complete code is -
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))
I'm able to decode Map json object as demonstrated here but not object with map field.
Any idea how to resolve this error?
The problem is that the generically derived decoder will try to parse the "pairs"
value as a Map[String, String]
, which means it will look for a JSON object, while what you have is a JSON array of objects.
If you're stuck with that MyConfig
definition and input that's shaped like that, you're probably best off writing your own decoder instead of deriving one with io.circe.generic.auto
. This is pretty straightforward with 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)
}
And then, assuming you've defined jsonStr
as above:
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)))
Alternatively you could either change MyConfig
so that the pairs
member is a List[Map[String, String]]
, or you could change the JSON schema (or whatever code is generating it) to omit the JSON array layer.