gpt4 book ai didi

scala - 为什么它不解码为 ADT 类型?

转载 作者:行者123 更新时间:2023-12-04 22:43:27 31 4
gpt4 key购买 nike

我正在尝试将以下字符串派生为适当的 ADT 类型:

res6: String = {"raw":"Hello","status":{"MsgSuccess":{}}} 

并使用 circe 库。

ADT 类型如下所示:
sealed trait MsgDoc {
}

final case class MsgPreFailure(raw: String, reasons: Chain[String]) extends MsgDoc

final case class MsgProceed(raw: String, status: MsgStatus) extends MsgDoc

MsgStatus 类型:
sealed trait MsgStatus {

}

case object MsgSuccess extends MsgStatus

final case class MsgFailure(reasons: Chain[String]) extends MsgStatus

final case class MsgUnknown(reason: String) extends MsgStatus

顺便说一句,我试过开车:
object MsgDocDerivation {

import shapeless.{Coproduct, Generic}

implicit def encodeAdtNoDiscr[A, Repr <: Coproduct](implicit
gen: Generic.Aux[A, Repr],
encodeRepr: Encoder[Repr]
): Encoder[A] = encodeRepr.contramap(gen.to)

implicit def decodeAdtNoDiscr[A, Repr <: Coproduct](implicit
gen: Generic.Aux[A, Repr],
decodeRepr: Decoder[Repr]
): Decoder[A] = decodeRepr.map(gen.from)
}

和执行:
object Main extends App {


val json = MsgProceed("Hello", MsgSuccess).asJson
println(json)
val adt = decode[MsgDoc](json.noSpaces)
println(adt)

}

结果我得到了:
{
"raw" : "Hello",
"status" : {
"MsgSuccess" : {

}
}
}
Left(DecodingFailure(CNil, List()))

如您所见,它没有正确地 decode

源代码可以在 https://gitlab.com/playscala/adtjson 中找到。

最佳答案

我不太确定 MsgDocDerivation 的目的是做什么——这似乎是不必要的和分散注意力的——但我认为关键问题是 circe 的编码(和解码)是由静态类型驱动的,而不是被编码的值的运行时类(或解码)。这意味着以下两个 JSON 值将不同:

val value = MsgProceed("Hello", MsgSuccess)

val json1 = value.asJson
val json2 = (value: MsgDoc).asJson

在你的情况下,以下对我来说很好用:
import cats.data.Chain

sealed trait MsgStatus
case object MsgSuccess extends MsgStatus
final case class MsgFailure(reasons: Chain[String]) extends MsgStatus
final case class MsgUnknown(reason: String) extends MsgStatus

sealed trait MsgDoc
final case class MsgPreFailure(raw: String, reasons: Chain[String]) extends MsgDoc
final case class MsgProceed(raw: String, status: MsgStatus) extends MsgDoc

import io.circe.generic.auto._, io.circe.jawn.decode, io.circe.syntax._

val value: MsgDoc = MsgProceed("Hello", MsgSuccess)
val json = value.asJson

val backToValue = decode[MsgDoc](json.noSpaces)

请注意, json 与您所看到的不同:
scala> json
res0: io.circe.Json =
{
"MsgProceed" : {
"raw" : "Hello",
"status" : {
"MsgSuccess" : {

}
}
}
}

scala> backToValue
res1: Either[io.circe.Error,MsgDoc] = Right(MsgProceed(Hello,MsgSuccess))

这是因为我已经执行了从 MsgProceedMsgDoc 的(类型安全)向上转换。无论如何,这通常是您使用 ADT 的方式——您不会传递静态类型为 case 类子类型的值,而是作为 sealed trait 基类型。

关于scala - 为什么它不解码为 ADT 类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55993981/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com