Я играю с примером ADT в документации Circe, чтобы воспроизвести проблему, которая у меня возникла с декодированием JSON.
Для этого я использую ShapesDerivation:
scala> object ShapesDerivation {
|
| implicit def encodeAdtNoDiscr[Event, Repr <: Coproduct](implicit
| gen: Generic.Aux[Event, Repr],
| encodeRepr: Encoder[Repr]
| ): Encoder[Event] = encodeRepr.contramap(gen.to)
|
| implicit def decodeAdtNoDiscr[Event, Repr <: Coproduct](implicit
| gen: Generic.Aux[Event, Repr],
| decodeRepr: Decoder[Repr]
| ): Decoder[Event] = decodeRepr.map(gen.from)
|
| }
defined object ShapesDerivation
ADT для декодирования состоит из двух значений: простого класса case и другого, который я выделил Encoder / Decoder (чтобы воспроизвести в минимальном примере проблему, которая у меня действительно есть):
scala> :paste
// Entering paste mode (ctrl-D to finish)
sealed trait Event
object Event {
case class Foo(i: Int) extends Event
case class Bar(f : FooBar) extends Event
case class FooBar(x : Int)
implicit val encoderFooBar : Encoder[FooBar] = new Encoder[FooBar] {
override def apply(a: FooBar): Json = Json.obj(("x", Json.fromInt(a.x)))
}
implicit val decodeFooBar: Decoder[FooBar] = new Decoder[FooBar] {
override def apply(c: HCursor): Result[FooBar] =
for {
x <- c.downField("x").as[Int]
} yield FooBar(x)
}
}
Затем, когда я пытаюсь декодировать простое значение, подобное этому, оно работает хорошо:
scala> import ShapesDerivation._
import ShapesDerivation._
scala> decode[Event](""" { "i" : 10 }""")
res1: Either[io.circe.Error,Event] = Right(Foo(10))
Но если я попытался декодировать что-то, что должно быть Bar
, которое содержит Foobar
, я получаю декодирование ошибка:
scala> decode[Event](""" { "x" : 10 }""")
res2: Either[io.circe.Error,Event] = Left(DecodingFailure(CNil, List()))
Но это работает, потому что я явно поставил имя поля класса дела:
scala> decode[Event](""" { "f" : { "x" : 10 }}""")
res7: Either[io.circe.Error,Event] = Right(Bar(FooBar(10)))
Я не знаю, как поместить поле класса дела, непосредственно JSON но я думаю, что невозможно добиться такого поведения. Причина, по которой я думаю, что это невозможно, состоит в том, как он узнает, что он соответствует классу хорошего случая, если нет поля, но я хочу быть уверен, что с помощью Circe нет способа сделать это