Reputation: 1
Reading at this documentation https://circe.github.io/circe/codecs/custom-codecs.html I understand that you should use the Circe KeyEncoder to define custom key types.
But I am confused if I want to encode a Map[K, V]
where
case class K(a1: String, a2: String)
case class V(b1: String, b2: String)
Upvotes: 0
Views: 1189
Reputation: 561
With class definitions;
case class K(a1: String, a2: String)
object K {
import io.circe._
implicit val encodeK: KeyEncoder[K] = (key: K) => s"${key.a1}-${key.a2}"
implicit val decodeK: KeyDecoder[K] = (s: String) => {
// Should be careful while parsing a K from String.
val kParts = s.split("-")
Some(K(kParts(0), kParts(1)))
}
}
and
case class V(b1: String, b2: String)
object V {
import io.circe._
implicit val encodeV: Encoder[V] = (v: V) => Json.obj(
("b1", Json.fromString(v.b1)),
("b2", Json.fromString(v.b2))
)
implicit val decodeV: Decoder[V] = (c: HCursor) => for {
b1 <- c.downField("b1").as[String]
b2 <- c.downField("b2").as[String]
} yield {
new V(b1, b2)
}
}
Conversion to/from JSON works as below:
object App {
import io.circe.syntax._
def main(args: Array[String]): Unit = {
val map: Map[K, V] = Map(
K("a11", "a21") -> V("b11", "b21"),
K("a12", "a22") -> V("b12", "b22"),
K("a13", "a23") -> V("b13", "b23")
)
val json = map.asJson
println(json)
println(json.as[Map[K, V]])
}
}
Upvotes: 1