找不到参数编码器的隐式值:io.circe.Encoder [com.sweetsoft.SapHealth]

时间:2019-05-30 14:16:39

标签: scala circe

我有以下代码,无法编译:

EOF

编译器抱怨:

import java.time.Instant

import io.circe.{Decoder, Encoder}
import io.circe.generic.auto._
import io.circe.syntax._

trait SapHealth {}

case class SapHealthRejected(reason: String) extends SapHealth

case class SapHealthAccepted(sapId: String, requestedAt: Long) extends SapHealth


object SapHealth {

  private val build: SapHealth = SapHealthAccepted(SapmockActor.system.name, Instant.now().getEpochSecond)

  val create: String = build.asJson.noSpaces

  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)

}

我想念什么?

3 个答案:

答案 0 :(得分:4)

您已专门将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编码器,我想这就是您想要的。

答案 1 :(得分:1)

特质SELECT应该被密封。

答案 2 :(得分:1)

对于案例类,您可以使用deriveEncoder/deriveDecoder。但是如果是复杂的类,你应该(我认为)为参数的类指定它。

https://circe.github.io/circe/codecs/semiauto-derivation.html

import io.circe._, io.circe.generic.semiauto._

case class Foo(a: Int, b: String, c: Boolean)

implicit val fooDecoder: Decoder[Foo] = deriveDecoder[Foo]
implicit val fooEncoder: Encoder[Foo] = deriveEncoder[Foo]