Suppose I have multiple types of ids defined as follows.
sealed trait Id {
val value: String
}
case class IdA(value: String) extends Id
case class IdB(value: String) extends Id
case class IdC(value: String) extends Id
These classes should be decoded from and encoded to the following JSON.
{
"id: "some-id"
}
How can I define some generic decoder/encoder for the id,
case class A(id: IdA, name: String, count: Int)
case class B(id: IdB, name: String, count: Int)
case class C(id: IdC, name: String, count: Int)
so that the classes above can be decoded from and encoded to the JSON below?
{
"id" : "some-id",
"name": "some-name",
"count": 2
}
if possible, I want the id field to be flexible for both decoder and encoder that is id maybe "id-x" in one case and "id-y" in another.
I have solved it by simply defining the following decoder and encoder.
import cats.implicits._
import io.circe.{Decoder, Encoder}
import shapeless._
implicit def encoderValueClass[T <: Id, V](implicit
g: Lazy[Generic.Aux[T, V :: HNil]],
e: Encoder[V]
): Encoder[T] = Encoder.instance { value =>
e(g.value.to(value).head)
}
implicit def idDecoder[T <: Id, V](implicit
g: Lazy[Generic.Aux[T, V :: HNil]],
d: Decoder[V]
): Decoder[T] = Decoder.instance { cursor =>
d(cursor).map { value =>
g.value.from(value :: HNil)
}
}