Предположим, у меня есть ADT в Scala:
sealed trait Base
case class Foo(i: Int) extends Base
case class Baz(x: String) extends Base
Я хочу закодировать значения этого типа в JSON, который выглядит следующим образом:
{ "Foo": { "i": 10000 }}
{ "Baz": { "x": "abc" }}
К счастью, это точноуниверсальная деривация кодирующей цепи обеспечивает!
scala> import io.circe.generic.auto._, io.circe.syntax._
import io.circe.generic.auto._
import io.circe.syntax._
scala> val foo: Base = Foo(10000)
foo: Base = Foo(10000)
scala> val baz: Base = Baz("abc")
baz: Base = Baz(abc)
scala> foo.asJson.noSpaces
res0: String = {"Foo":{"i":10000}}
scala> baz.asJson.noSpaces
res1: String = {"Baz":{"x":"abc"}}
Проблема заключается в том, что использование кодировочной системы зависит от статического типа выражения, которое мы кодируем.Это означает, что если мы пытаемся декодировать один из классов case напрямую, мы теряем дискриминатор:
scala> Foo(10000).asJson.noSpaces
res2: String = {"i":10000}
scala> Baz("abc").asJson.noSpaces
res3: String = {"x":"abc"}
… но мне нужна кодировка Base
, даже если статический тип равен Foo
.Я знаю, что могу определить явные экземпляры для всех классов дел, но в некоторых случаях их может быть много, и я не хочу перечислять их.
(Обратите внимание, что этовопрос, который возник несколько раз - например, здесь .)