我是用Circe库工作的,想学习一下这方面的知识。请看下面的代码。
import io.circe.generic.auto._
import io.circe.syntax._
import io.circe.{Decoder, Encoder, Json}
sealed trait Something
case class Name(val name: String) extends Something
class myClass[T](name: Option[Name] = None, data: Option[Seq[T]] = None) {
// convert an arbitrary sequence to json
def seqToJson[T](lst: Seq[T])(implicit encoder: Encoder[T]): Json = {
lst.asJson
}
val mydata: Json = seqToJson(data.get)
}
object Trace extends App {
val name = new myClass(Some(Name("Noob")))
}
继这里的出色回答之后 链接我现在正在尝试一个例子,在这个例子中,我可以在一个类中建立一个编码器。
然而,当我运行上面的代码时,它说:"无法找到参数encoder的隐式值:io.circe.Encoder[T][错误]val mydata::"。
无法找到参数 encoder 的隐式值:io.circe.Encoder[T] [error] val mydata.Json = seqToJson(data.get) [error] ^mydata.Json = seqToJson(data.get) [error] ^mydata.Json = seqToJson(data.get) [error] ^mydata.Json = seqToJson(data.get) [error] ^mydata.Json = seqToJson(data.get) [error] ^mydata.Json = seqToJson(data.get) [error] ^mydata.Json = seqToJson(data.get) Json = seqToJson(data.get) [错误] ^。
现在我的问题是,为什么会出现这种情况。当我把隐式编码器的定义移到类里面的时候,为什么编译器不能接收到如何使用它?
我也尝试了其他的方法,就是移动我定义隐式编码器的位置。
import io.circe.generic.auto._
import io.circe.syntax._
import io.circe.{Decoder, Encoder, Json}
sealed trait Something
case class Name(val name: String) extends Something
class myClass[T](name: Option[Name] = None, data: Option[Seq[T]] = None)(implicit encoder: Encoder[T]) {
// convert an arbitrary sequence to json
def seqToJson[T](lst: Seq[T]): Json = {
lst.asJson
}
val mydata: Json = seqToJson(data.get)
}
object Trace extends App {
val name = new myClass(Some(Name("Noob")))
}
这就出现了以下错误:
无法找到参数编码器的隐式值: io.circe.Encoder[Seq[T]]模糊的隐式值:
[error] both lazy value encodeDuration in object Encoder of type io.circe.Encoder[java.time.Duration]
[error] and lazy value encodeInstant in object Encoder of type io.circe.Encoder[java.time.Instant]
[error] match expected type io.circe.Encoder[T]
[error] Error occurred in an application involving default arguments.
[error] val name = new myClass(Some(Name("Noob")))
所以我的问题是,如何让隐式定义的编码器进入Class的范围。如果有任何理论解释的答案,将非常感激!
EDIT:用了Ivan的结构,成功了!
import io.circe.syntax._
import io.circe.{Decoder, Encoder, Json}
class myClass[T](data: Seq[T])(implicit encoder: Encoder[T]) {
def seqToJson(lst: Seq[T]): Json = {
lst.asJson
}
}
object Trace extends App {
println(new myClass[Int](data = Seq(1,2,3)))
}
现在我的问题是,为什么会发生这种情况。当我把隐式编码器的定义移到类里面时,为什么编译器不能接收到如何使用它?
答案是没有隐式的 Encoder[T]
属于课的范围 myClass
.
你可以通过移动来解决它 (implicit encoder: Encoder[T])
到构造器,你做到了。
此外,你还定义了通用类型 T
两处
class myClass[T]
和
def seqToJson[T]
你应该只保留一个在 myClass
找不到参数 encoder 的隐式值:io.circe.Encoder[Seq[T]] 含糊不清的隐式值。
这是由于缺少通用类型的问题造成的。你没有指定类型 T
当创建一个新的 myClass
. 如果你这样做,它会编译。
例如:
val name = new myClass[Int](Some(Name("Noob")))
这将在运行时失败,在行 seqToJson(data.get)
因为你没有通过任何 data
.
我怎样才能让隐式定义的编码器进入类的作用域?
构造函数是一个不错的选择
考虑以下简化的片段
def f[T](v: Option[T] = None) = v
f() // T is inferred as Nothing
这里的类型参数 T
被推断为 Nothing
因为 None
定义为
case object None extends Option[Nothing]
因此,在以下情况下
def f[T](v: Option[T] = None)(implicit ev: Encoder[T]) = v
f() // error because requiring Encoder[Nothing] capability
实际上我们要求 Encoder[Nothing]
哪些错误。事实上,你可以模拟类似的错误,只需请求
implicitly[Encoder[Nothing]]
其中错误的
Error: diverging implicit expansion for type io.circe.Encoder[Nothing]
starting with lazy value encodeZoneOffset in object Encoder
不知道为什么特别提到 encodeZoneOffset
但这可能与隐式搜索的工作原理和 encodeZoneOffset
是 最后的 隐含价值 Encoder
伴侣。