【问题标题】:Generic json decoder trait with Circe implementation [duplicate]具有Circe实现的通用json解码器特征[重复]
【发布时间】:2017-04-24 20:17:18
【问题描述】:

我有一个 trait 用于注入 json 解码器作为我项目组件的依赖项:

trait JsonDecoder {
  def apply[T](s: String): Option[T]
}

当我尝试使用Circe 实现它时:

import io.circe.generic.auto._
import io.circe.parser.decode

case class CirceJsonDecoder() extends JsonDecoder {
  def apply[T](s: String): Option[T] = {
    decode[T](s).fold(_ => None, s => Some(s)) 
  }
}

然后运行:

case class C()

def test(d: JsonDecoder) = d[C]("{}")

test(CirceJsonDecoder())

它没有编译错误:

could not find implicit value for parameter decoder: io.circe.Decoder[T]

我尝试为T 添加ClassTagTypeTagWeakTypeTag 上下文边界,但仍然找不到Decoder 的隐含值。

我无法将Decoder 上下文绑定或隐式参数添加到JsonDecoder.apply,因为使用它的组件不应该知道实现细节。

我应该如何提供隐式io.circe.Decoder?可能有什么方法可以从TypeTag获得它?

【问题讨论】:

  • 据我了解,您尝试修复它的方式(通过 ClassTag/TypeTag 添加反射),您假设 circe 使用反射来派生 json 编解码器。事实并非如此。相反,circe 在编译时派生编解码器,因此它需要的不仅仅是T 关于类型的更多信息。您可以尝试shapeless.LabelledGenericshapless.Generic 上下文绑定。

标签: scala circe


【解决方案1】:

我认为你不能不以任何涉及 circe 的方式影响你的 apply 方法签名。 如果可以的话,这意味着 circe.auto_ 能够为任何类型 T 引入隐式解码器,这是不正确的。

AFAIK,没有比在你的函数中添加隐式 Decoder 更好的类型注释来表明它实际上知道如何处理这种类型(如果你愿意,你可以使用 T: Decoder 版本,但它是一样的最后)。

【讨论】:

  • 谢谢!我赞成你的回答,但我发现之前问过同样的问题,并将其标记为重复。我将在那里发布我的最终解决方案。正如你和那个问题中的人所建议的那样,我使用类型类方法。
猜你喜欢
  • 2016-08-28
  • 1970-01-01
  • 2023-04-10
  • 2020-06-05
  • 2022-10-07
  • 2018-09-20
  • 1970-01-01
  • 2017-03-31
  • 2019-12-08
相关资源
最近更新 更多