如何为抽象类编写循环解码器/编码器

时间:2020-06-02 06:27:30

标签: scala circe

我需要为akka.http.scaladsl.model.HttpHeader编写解码器/编码器

abstract class HttpHeader extends jm.HttpHeader with ToStringRenderable {
  def name: String
  def value: String
  def lowercaseName: String
  def is(nameInLowerCase: String): Boolean = lowercaseName == nameInLowerCase
  def isNot(nameInLowerCase: String): Boolean = lowercaseName != nameInLowerCase
}

我尝试使用衍生编码和解码,但是没有用

implicit val jsonDecoder: Decoder[HttpHeader] = deriveDecoder[HttpHeader]
implicit val jsonEncoder: Encoder[HttpHeader] = deriveEncoder[HttpHeader]

只是出现错误could not find Lazy implicit value of type io.circe.generic.decoding.DerivedDecoder[akka.http.scaladsl.model.HttpHeader]

1 个答案:

答案 0 :(得分:4)

Circe的通用派生(deriveDecoder等)仅适用于它识别为“代数数据类型”的类型(在Scala中表示案例类和案例类的密封层次结构)。

您绝对可以将Circe与HttpHeader之类的类型一起使用,但是您必须更加明确地说明它们的编码方式。造成这种情况的部分原因是,您可以通过多种可能的方式对这种类型的值进行编码,例如您是否要在序列化中包含诸如lowercaseName值之类的派生属性?

这是为此类型编写实例的一种可能方式:

import io.circe.{Decoder, Encoder}

abstract class HttpHeader {
  def name: String
  def value: String
  def lowercaseName: String
  def is(nameInLowerCase: String): Boolean = lowercaseName == nameInLowerCase
  def isNot(nameInLowerCase: String): Boolean = lowercaseName != nameInLowerCase
}

implicit val decodeHttpHeader: Decoder[HttpHeader] =
  Decoder.forProduct2("name", "value") {
    (n: String, v: String) => new HttpHeader {
      val name = n
      val value = v
      def lowercaseName = v.toLowerCase
    }
  }

implicit val encodeHttpHeader: Encoder[HttpHeader] =
  Encoder.forProduct2("name", "value") { header =>
    (header.name, header.value)
  }

这是这样的:

scala> import io.circe.syntax._, io.circe.jawn.decode
import io.circe.syntax._
import io.circe.jawn.decode

scala> decode[HttpHeader]("""{ "name": "ABC", "value": "XYZ" }""")
res0: Either[io.circe.Error,HttpHeader] = Right($anon$1@dcd9c89b)

scala> res0.map(_.asJson)
res1: scala.util.Either[io.circe.Error,io.circe.Json] =
Right({
  "name" : "ABC",
  "value" : "XYZ"
})

您还可以获取较低级别的内容,直接使用flatMap或其他组合器来构建实例,但是在大多数情况下,forProductN这样的情况就是您想要的。

相关问题