【问题标题】:Wrapping circe decoder with own codecs (implicits)用自己的编解码器包装 circe 解码器(隐式)
【发布时间】:2019-01-26 06:46:42
【问题描述】:

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

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

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

有没有一种方法可以设置这个,所以我只需要一个导入? circe 的 deriveDecoder 方法的一种“代理”,它仍然会使用我的隐式 MyAdt

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

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

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

【问题讨论】:

    标签: scala implicit circe


    【解决方案1】:

    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 之类的东西。

    【讨论】:

    • 有趣的是,我在发布之前尝试过这个,但失败了。你关于两次导入相同的隐式的中间警告是我认为的问题,因为我写的测试在 json 包中,我相信存在冲突。现在一切正常 - 谢谢。我最终可能会编写自己的 @JsonCodec 版本来包含我的自定义解码器,这样我的用户就不必为导入而烦恼
    猜你喜欢
    • 2017-06-12
    • 2017-11-27
    • 1970-01-01
    • 2017-08-25
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 2017-08-21
    • 1970-01-01
    相关资源
    最近更新 更多