1

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.

d-_-b
  • 4,142
  • 6
  • 28
  • 43

2 Answers2

1

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)
    }
  }
d-_-b
  • 4,142
  • 6
  • 28
  • 43
0

This answer https://stackoverflow.com/a/75627162/21293767 with Circe decoder for generic case class with default parameters using generics with case class MyClass[T] might help