【问题标题】:circe encoding putting :: when a list of case class from trait is not sealedcirce encoding put :: 当特征中的案例类列表未密封时
【发布时间】:2020-09-10 17:22:53
【问题描述】:

大家好,我在使用 circe 库在 json 和 scala 案例类之间进行转换时遇到问题,我们将不胜感激。

过去我有这样的 ADT。

sealed trait Sons

case class Son1(name: String, belongings: List[String]) extends Sons
case class Son2(lastName: String, belongings: List[String]) extends Sons

并且没有任何问题,但现在由于设计,女巫这个特性的文件是,改变成本很高,我们必须从特性中移除密封,所以现在我们有了这个(与不同文件/库中的儿子)

trait Sons

case class Son1(name: String, belongings: List[String]) extends Sons
case class Son2(lastName: String, belongings: List[String]) extends Sons

当尝试将子列表从 Scala 转换为 json 时,库会将 :: 放在列表之前,从而产生问题,如本例所示。

object Test extends App{


implicit val encoderSon1: Encoder[Son1]=deriveEncoder[Son1]
  implicit val decoderSon1: Decoder[Son1]=deriveDecoder[Son1]
  implicit val encoderSon2: Encoder[Son2]=deriveEncoder[Son2]
  implicit val decoderSon2: Decoder[Son2]=deriveDecoder[Son2]

  implicit val encoderSon: Encoder[Sons] = Encoder.instance {
    case son1: Son1 => son1.asJson
    case son2: Son2 => son2.asJson
  }

  implicit val DecoderSon: Decoder[Sons] =
    List[Decoder[Sons]](
      Decoder[Son1].widen,
      Decoder[Son2].widen
    ).reduceLeft(_ or _)

  implicit val encoderSonList: Encoder[List[Sons]] = deriveEncoder
  implicit val DecoderSonList: Decoder[List[Sons]] = deriveDecoder

  val sonsList: List[Sons] = List(Son1("James",List()),Son2("Mike",List()))
  println(s"1->${sonsList}")
  println(s"2->${sonsList.asJson.noSpaces}")
  val andBack=decode[List[Sons]](sonsList.asJson.noSpaces).fold(fa=>fa.getMessage,fb=>fb.toString())
  println(s"3->${andBack}")
}

打印是 printint

1->List(Son1(James,List()), Son2(Mike,List()))
2->{"::":[{"name":"James","belongings":[]},{"lastName":"Mike","belongings":[]}]}
3->Attempt to decode value on failed cursor: DownField(head),DownField(::)

问题当然是我不希望在转换为 JSON 时将列表放入名为 :: 的字段中。

感谢您提供的任何帮助:D

【问题讨论】:

    标签: json scala encoding scala-cats circe


    【解决方案1】:

    不要对List 使用半自动 - 半自动使用的机制与其他派生稍有不同,例如避免以下问题:

    implicit val x: X = implicitly[X] // uses val x, so we have cyclic dependency = error in runtime
    

    因此,当您在此处使用半自动时,来自 EncoderDecoderList 实例将被忽略,而宏会为 List ADT 生成代码 - 即 case class ::case object Nil

    如果你删除

    
      implicit val encoderSonList: Encoder[List[Sons]] = deriveEncoder
      implicit val DecoderSonList: Decoder[List[Sons]] = deriveDecoder
    

    它会再次起作用。

    【讨论】:

      猜你喜欢
      • 2021-03-08
      • 2018-10-31
      • 2016-08-19
      • 2022-07-21
      • 2020-03-23
      • 2016-08-28
      • 2015-05-26
      • 2018-09-20
      • 1970-01-01
      相关资源
      最近更新 更多