带有自己的编解码器的环绕式解码器(隐式)

时间:2018-08-20 07:09:21

标签: scala implicit circe

我正在使用通过deriveDecoder提供的半自动解码器推导。我有一些自定义ADT,我想将自己的解码器传递给我,以便在解析隐式解码器时可以循环使用。

package object json {
  implicit val myAdtDecoder: Decoder[MyAdt] = ...
}

这行得通,尽管我现在需要在文件中调用circe的deriveDecoder进行两次导入。

有没有一种方法可以进行设置,因此我只需要一次导入?可以绕开deriveDecoder方法的一种“代理”,它仍将我的隐式用于MyAdt吗?

package object json {
  implicit val myAdtDecoder: Decoder[MyAdt] = ...

  implicit def deriveDecoder[T]: Decoder[T] = ...
}

请注意,如果我在此处明确指定了T,就不会有解决此问题的问题,但是我想保持它的通用性,使其可以适用于任何T

1 个答案:

答案 0 :(得分:0)

deriveDecoder在这里将是自动的(您不想自己叫它),但是您尝试导入半自动版本。

使用自动方法,您可以执行以下操作:

trait ExtendedAuto extends io.circe.generic.AutoDerivation {

  implicit val myAdtDecoder: Decoder[MyAdt] = ...
}

package object json extends ExtendedAuto

您必须注意不要(偶然)两次导入相同的隐式变量,因为这样导出将失败。但是,如果您遵守纪律(例如,始终只将包对象导入所有地方),那应该没问题。

使用Semiauto会有所不同:

package object json {
  implicit val myAdtDecoder: Decoder[MyAdt] = ...

  // signatures copy-pasted from io.circe.generic.semiauto
  import io.circe.generic.semiauto
  final def deriveDecoder[A](implicit decode: Lazy[DerivedDecoder[A]]): Decoder[A] = semiauto.deriveDecoder[A]
  final def deriveEncoder[A](implicit encode: Lazy[DerivedObjectEncoder[A]]): ObjectEncoder[A] = semiauto.deriveEncoder[A]
}

但是,如果您使用的是半自动,则可能会将内容放入伴随对象中,以避免同一编解码器的多个派生。在这种情况下,您可以考虑使用类似@JsonCodec的东西。