Вы специально повышали build
до SapHealth
, но вы не предоставляете экземпляр Encoder
для SapHealth
(только SapHealthAccepted
), и circe-generic не может получить его, потому чтовы не запечатали иерархию признаков.
Наиболее простым решением было бы добавить sealed
:
import io.circe.{Decoder, Encoder}
import io.circe.generic.auto._
import io.circe.syntax._
sealed trait SapHealth {}
case class SapHealthRejected(reason: String) extends SapHealth
case class SapHealthAccepted(sapId: String, requestedAt: Long) extends SapHealth
object SapHealth {
implicit val encodeFieldType: Encoder[SapHealthAccepted] =
Encoder.forProduct2("sap-id", "requested_at")(SapHealthAccepted.unapply(_).get)
implicit val decodeFieldType: Decoder[SapHealthAccepted] =
Decoder.forProduct2("sap-id", "requested_at")(SapHealthAccepted.apply)
private val build: SapHealth = SapHealthAccepted("foo", 123L)
val create: String = build.asJson.noSpaces
}
Обратите внимание, что вам также необходимо изменить определения, чтобы избежать появления нулевого значения-исключение указателя из-за порядка инициализации (если вы поставите create
перед encodeFieldType
, производный кодер SapHealth
попытается использовать encodeFieldType
до его инициализации).С приведенной выше перестановкой это работает просто отлично:
scala> SapHealth.create
res2: String = {"SapHealthAccepted":{"sap-id":"foo","requested_at":123}}
Обратите внимание, что производный SapHealth
кодировщик использует ваш пользовательский SapHealthAccepted
кодировщик, который, как я полагаю, вам нужен.