【问题标题】:Json-circe can't derive encoder for subtype of sealed traitJson-circe 无法为密封特征的子类型派生编码器
【发布时间】:2018-09-20 08:38:06
【问题描述】:

为什么会出现错误could not find Lazy implicit value of type io.circe.generic.decoding.DerivedDecoder[A$A6.this.Bar] 在以下代码中:

import io.circe.{Decoder, DecodingFailure, Encoder, HCursor, Json, ObjectEncoder}
import io.circe.generic.semiauto._
import io.circe.generic.semiauto._
import io.circe.syntax._
import io.circe.parser._

sealed trait Foo
object Foo {
  case class Foo1(foo1: String) extends Foo
  case class Foo2(foo2: String) extends Foo

}

case class Bar(foo1: Foo.Foo1)

implicit lazy val FooDecoder: Decoder[Foo] = new Decoder[Foo] {
  final def apply(c: HCursor): Decoder.Result[Foo] = {
    def decode(messageType: String, payload: Json): Decoder.Result[Foo] = messageType match {
      case "Foo1" => payload.as[Foo.Foo1](deriveDecoder[Foo.Foo1])
      case "Foo2" => payload.as[Foo.Foo2](deriveDecoder[Foo.Foo2])
    }

    for {
      messageType <- c.downField("type").as[String]
      payload <- c.downField("payload").focus.toRight(DecodingFailure("payload field is not present", Nil))
      in <- decode(messageType, payload)
    } yield in
  }
}

implicit lazy val barDecoder: Decoder[Bar] = deriveDecoder[Bar]

parse("""
  |{ "foo1": {
  |  "type" : "Foo1",
  |    "payload": {
  |      "foo1": "bar"
  |    }
  |  }
  |}
""".stripMargin)
  .flatMap(json => json.as[Bar])

它使用case class Bar(foo1: Foo) 编译,但Foo1Foo 的子类型,我不想为Foo1Foo2 编写重复的编码器。如何解决这个问题?

【问题讨论】:

    标签: json scala circe


    【解决方案1】:

    尝试定义实例Decoder[Foo.Foo1]Decoder[Foo.Foo2](提取通用公共部分以避免代码重复)并使用它们派生Decoder[Foo]

      def helper[T <: Foo : DerivedDecoder](s: String): Decoder[T] = new Decoder[T] {
        final def apply(c: HCursor): Decoder.Result[T] = {
          def decode(messageType: String, payload: Json): Decoder.Result[T] = messageType match {
            case _ if messageType == s => payload.as[T](deriveDecoder[T])
          }
    
          for {
            messageType <- c.downField("type").as[String]
            payload <- c.downField("payload").focus.toRight(DecodingFailure("payload field is not present", Nil))
            in <- decode(messageType, payload)
          } yield in
        }
      }
    
      implicit lazy val foo1Decoder: Decoder[Foo.Foo1] = helper[Foo.Foo1]("Foo1")
      implicit lazy val foo2Decoder: Decoder[Foo.Foo2] = helper[Foo.Foo2]("Foo2")
      implicit lazy val fooDecoder: Decoder[Foo] = deriveDecoder[Foo]
      implicit lazy val barDecoder: Decoder[Bar] = deriveDecoder[Bar]
    

    【讨论】:

      猜你喜欢
      • 2016-08-19
      • 2021-03-08
      • 2018-10-31
      • 2022-10-04
      • 2016-08-28
      • 2017-11-27
      • 1970-01-01
      • 1970-01-01
      • 2020-09-10
      相关资源
      最近更新 更多