我如何用 circe 定义一些通用的 decoder/encoder?
How can I define some generic decoder/encoder with circe?
假设我有多种类型的id定义如下。
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
这些 类 应该被解码并编码为以下 JSON.
{
"id: "some-id"
}
如何为 id 定义一些通用的 decoder/encoder,
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)
以便上面的 类 可以从下面的 JSON 解码并编码成下面的 JSON?
{
"id" : "some-id",
"name": "some-name",
"count": 2
}
如果可能的话,我希望 id 字段对于解码器和编码器都是灵活的,在一种情况下 id 可能是“id-x”,在另一种情况下可能是“id-y”。
我已经通过简单定义以下解码器和编码器解决了。
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)
}
}
假设我有多种类型的id定义如下。
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
这些 类 应该被解码并编码为以下 JSON.
{
"id: "some-id"
}
如何为 id 定义一些通用的 decoder/encoder,
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)
以便上面的 类 可以从下面的 JSON 解码并编码成下面的 JSON?
{
"id" : "some-id",
"name": "some-name",
"count": 2
}
如果可能的话,我希望 id 字段对于解码器和编码器都是灵活的,在一种情况下 id 可能是“id-x”,在另一种情况下可能是“id-y”。
我已经通过简单定义以下解码器和编码器解决了。
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)
}
}