【问题标题】:How can I define some generic decoder/encoder with circe?如何用 circe 定义一些通用解码器/编码器?
【发布时间】:2021-02-15 21:30:05
【问题描述】:

假设我有多种类型的 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 定义一些通用解码器/编码器,

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 中解码和编码?

{
   "id" : "some-id",
   "name": "some-name",
   "count": 2
}

如果可能的话,我希望 id 字段对于解码器和编码器都是灵活的,在一种情况下 id 可能是“id-x”,在另一种情况下可能是“id-y”。

【问题讨论】:

  • 您可以为 trait Id 创建一个自定义 Codec,定义它应该如何工作。
  • 您能提供一些示例实现吗?
  • 我觉得您将几个问题混为一谈。哪个 json 应该解码成哪个类?哪些类应该编码到哪些 jsons 中?

标签: scala circe


【解决方案1】:

我已经通过简单地定义以下解码器和编码器来解决它。

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)
    }
  }

【讨论】:

    猜你喜欢
    • 2020-05-31
    • 2017-06-12
    • 2023-03-04
    • 1970-01-01
    • 2019-01-26
    • 2017-11-27
    • 2019-02-25
    • 2018-09-15
    • 1970-01-01
    相关资源
    最近更新 更多