scala 包含类型参数化类的示例的编码类

s5a0g9ez  于 2024-01-08  发布在  Scala
关注(0)|答案(1)|浏览(132)

我无法处理使用circeFL类的示例编码为JSON的问题。我提供了两个自定义编码器-分别用于CSRS类。然而,在编译过程中,我仍然得到:

could not find implicit value for parameter encoder: io.circe.Encoder[FL]

字符串
当我尝试编译时:

import io.circe.{Encoder, Json}
import io.circe.generic.extras.auto._
import io.circe.syntax._
FL(List.empty).asJson

    
implicit val rsEncoder: Encoder[RS] = Encoder.instance[RS] { x =>
    Json.obj(
    )
}

implicit val csEncoder: Encoder[CS] = Encoder.instance[CS] { x =>
    Json.obj(
    )
}

sealed trait A {
    def s: Int
}

object A {
    case class RS(s: Int, d: Double) extends A
    case class CS(s: Int, l: Double) extends A
}

case class FSI[T <: A](sts: T)

final case class E(
    segs: Seq[FSI[_ <: A]] = Seq.empty,
)

final case class FL(es: List[List[E]])


我看到的唯一方法是在FL类级别上尝试实现编码器-但是我想避免它,因为这个类包含更多的元素(但是它们在编码方面没有问题)。你能帮助我做/解决它吗?或者可能存在理论上的原因,这是不可能的。

bqf10yzr

bqf10yzr1#

我研究了你的代码,我认为有两件事让喀耳刻感到困惑:
1.要做到这一点,看起来需要添加一个配置来指定一个A(这是有意义的,因为仅从结构中无法返回到您正在编码的A的子类型
1.看起来不可能对Seq[_ <: A]进行编码(至少不是自动的),所以你只需要使用Seq[A](我认为这不会限制你的实践,但很高兴纠正)
以下内容似乎按预期工作:

import io.circe.{Encoder, Json}
import io.circe.generic.extras.auto._
import io.circe.syntax._
import io.circe.generic.extras.Configuration

implicit val genDevConfig: Configuration =
  Configuration.default.withDiscriminator("type")

sealed trait A {
    def s: Int
}

object A {
    case class RS(s: Int, d: Double) extends A
    case class CS(s: Int, l: Double) extends A
}

case class FSI[T <: A](sts: T)

final case class E(
    segs: Seq[FSI[A]] = Seq.empty,
)

final case class FL(es: List[List[E]])

FL(List.empty).asJson.noSpaces
FL(List(List(E(List(FSI(A.RS(1, 4.2))))))).asJson.noSpaces

字符串
请注意,我甚至不必包含RSCS的自定义编码器。
你可以使用这段代码here on Scastie(我配置为使用Scala 2.13和Circe 0.14.3,根据你最初的帖子,它似乎是朝着你当前依赖项的方向发展的)。
如果你想使用自定义编码器,你必须通过显式地拥有一个Encoder[A]来手动分派到每种类型,如下面的代码片段所示:

import io.circe.{Encoder, Json}
import io.circe.generic.extras.auto._
import io.circe.generic.extras.Configuration
import io.circe.syntax._

implicit val config: Configuration = Configuration.default

implicit val rsEncoder: Encoder[A.RS] = Encoder.instance[A.RS] { x =>
  Json.obj(
  )
}

implicit val csEncoder: Encoder[A.CS] = Encoder.instance[A.CS] { x =>
  Json.obj(
  )
}

implicit val encodeA: Encoder[A] = Encoder.instance[A] {
  case rs: A.RS => rs.asJson
  case cs: A.CS => cs.asJson
}

sealed trait A {
  def s: Int
}

object A {
  case class RS(s: Int, d: Double) extends A
  case class CS(s: Int, l: Double) extends A
}

case class FSI[T <: A](sts: T)

final case class E(
    segs: Seq[FSI[A]] = Seq.empty
)

final case class FL(es: List[List[E]])

FL(List.empty).asJson.noSpaces
FL(List(List(E(List(FSI(A.RS(1, 4.2))))))).asJson.noSpaces


这个例子是also available on Scastie。请注意,在这种情况下,如果需要将这些JSON对象解析为相同的类型,仍然必须使用某种形式的JavaScript。
我用信息from the Circe documentation about ADT encoding写了这个。

相关问题