我的问题与mixel在此处提供的第二种解决方案有关:Scala Circe with generics
请注意,在Circe的当前版本中,名为Circe的特征已重命名为AutoDerivation。
我正在使用mixel在他的StackOverflow解决方案中提供的解决方案,但无法使其正常工作。我已经尝试过将Circe版本更新为最新版本,并确保已导入Macro Paradise插件,但仍然没有运气。
这是我的代码。第一个是它自己的文件,称为CirceGeneric。
import io.circe._
import io.circe.parser._
import io.circe.generic.extras._
object CirceGeneric {
trait JsonEncoder[T] {
def apply(in: T): Json
}
trait JsonDecoder[T] {
def apply(s: String): Either[Error, T]
}
object CirceEncoderProvider {
def apply[T: Encoder]: JsonEncoder[T] = new JsonEncoder[T] {
def apply(in: T) = Encoder[T].apply(in)
}
}
object CirceDecoderProvider {
def apply[T: Decoder]: JsonDecoder[T] = new JsonDecoder[T] {
def apply(s: String) = decode[T](s)
}
}
}
object Generic extends AutoDerivation {
import CirceGeneric._
implicit def encoder[T: Encoder]: JsonEncoder[T] = CirceEncoderProvider[T]
implicit def decoder[T: Decoder]: JsonDecoder[T] = CirceDecoderProvider[T]
}
第二个是使用Akka函数responseAs的单元测试方法。该方法出现在名为BaseServiceTest的类中。
def responseTo[T]: T = {
def response(s: String)(implicit d: JsonDecoder[T]) = {
d.apply(responseAs[String]) match {
case Right(value) => value
case Left(error) => throw new IllegalArgumentException(error.fillInStackTrace)
}
}
response(responseAs[String])
}
这个想法是将responseAs [String]的结果(返回一个字符串)转换为解码的case类。
该代码的行为不符合预期。 Intellij不会检测到任何缺少的隐式内容,但是当编译时间到来时,我遇到了问题。我应该提到BaseServiceTest文件包含CirceGeneric._和Generic._的导入,因此缺少导入语句不是问题。
[错误] [...] / BaseServiceTest.scala:59:找不到参数d的隐式值:[...] CirceGeneric.JsonDecoder [T] [错误]响应(responseAs [String])
或者没有发生从Decoder [T]到JsonDecoder [T]的隐式转换,或者没有创建Decoder [T]实例。无论哪种方式,都出了问题。
答案 0 :(得分:1)
您仍然需要绑定到Decoder
的{{1}}或JsonDecoder
上下文。
responseTo
这是因为您的所有代码以及链接的答案中的mixel的代码实际上都是关于从def responseTo[T : Decoder]: T = ...
到Decoder
特质的抽象,可用于跨库支持。但是,如果没有基础JsonDecoder
实例,您仍然无法构建一个实例。
现在,有一些方法可以自动为Decoder
中包含的案例类生成Decoder
,但是现在在您的代码中
circe.generics.auto
您要让编译器能够为任意类型提供隐式def responseTo[T]: T = {
def response(s: String)(implicit d: JsonDecoder[T]) = ...
...
}
(即,在您的设置中,JsonDecoder
)实例。正如链接问题的公认答案所解释的那样,这是不可能的。
您需要将隐式解析延迟到知道您要处理的类型的程度,尤其是可以为其提供Decoder
实例。
编辑:在您对不能创建所有类型的Decoder[T]
的问题的评论中的答复...
我对链接问题的理解是,他们正试图抽象出JsonDecoder
库,以便允许换出JSON库实现。这样做如下:
添加circe
类型的类
有一个包JsonDecoder
,其中包含隐式内容(使用Circe),用于通过扩展json
具有外部代码,仅引用AutoDerivation
并将隐式内容导入JsonDecoder
包中
然后,所有的JSON序列化和隐式解析都可以实现,而无需调用代码引用json
,并且很容易将io.circe
/ json
切换到另一个JSON库,如果想要的。但是您仍然必须使用JsonDecoder
上下文绑定,并且只能使用可构造此类隐式的类型。并不是每种类型。