首页 > 解决方案 > Circe:将隐式编码器移动到泛型类中

问题描述

我正在与 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")))
}

继这里的优秀答案之后:Link,我现在正在尝试一个可以将编码器构建到类中的示例。

但是,当我运行上面的代码时,它说:

找不到参数编码器的隐含值:io.circe.Encoder[T] [error] val mydata: Json = seqToJson(data.get) [error] ^

现在我的问题是,为什么会发生这种情况。当我将隐式编码器的定义移动到类内部时,为什么编译器无法拾取如何使用它?

我也尝试了其他方法,即移动到我定义隐式编码器的位置:

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")))

所以我的问题是,我如何将隐式定义的编码器纳入类的范围。任何解释该理论的答案将不胜感激!

编辑:使用伊万的结构,它的工作原理!

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)))
}

标签: scalagenericstypesshapelesscirce

解决方案


现在我的问题是,为什么会发生这种情况。当我将隐式编码器的定义移动到类内部时,为什么编译器无法拾取如何使用它?

Encoder[T]答案是在 class 范围内没有隐式可用myClass

您可以通过移动(implicit encoder: Encoder[T])到构造函数来修复它,您已经这样做了。

此外,您T在两个地方定义泛型类型

class myClass[T]

def seqToJson[T]

你应该只保留一个myClass

找不到参数编码器的隐含值:io.circe.Encoder[Seq[T]] 不明确的隐含值:

这是由于缺少泛型类型的问题造成的。T创建新实例时没有指定类型myClass。如果你这样做,它将编译。

例如,

val name = new myClass[Int](Some(Name("Noob")))

这将在运行时在线失败,seqToJson(data.get)因为您没有传入任何data.

我如何将隐式定义的编码器纳入类的范围

构造函数是一个不错的选择


推荐阅读