为什么我会收到错误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)
进行编译,但Foo1
是Foo
的子类型,我不想为Foo1
和Foo2
编写重复的编码器。如何解决这个问题?
答案 0 :(得分: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]