Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ADT Json序列化/反序列化_Json_Scala_Algebraic Data Types_Circe - Fatal编程技术网

ADT Json序列化/反序列化

ADT Json序列化/反序列化,json,scala,algebraic-data-types,circe,Json,Scala,Algebraic Data Types,Circe,在使用Circe对Scala中的代数数据类型进行序列化和反序列化时,我在web上的文档和一些示例之后尝试了以下示例: sealed trait StringData case class Data2(f1: String, f2: String) extends StringData case class Data3(f1: String, f2: String, f3: String) extends StringData object StringData { //

在使用Circe对Scala中的代数数据类型进行序列化和反序列化时,我在web上的文档和一些示例之后尝试了以下示例:

  sealed trait StringData
  case class Data2(f1: String, f2: String) extends StringData
  case class Data3(f1: String, f2: String, f3: String) extends StringData

  object StringData {
    // ===> does not work, always picks Data2 type
    implicit val decodeData: Decoder[Data] = Decoder[OptionsData].map[Data](identity).or(Decoder[TextData].map[Data](identity))

    implicit val encodeData: Encoder[StringData] = Encoder.instance {
      case d2 @ Data2( _,_) => d2.asJson
      case d3 @ Data3( _, _, _) => d3.asJson
    }

    def toJson(s: StringData): String = s.asJson.noSpaces
    def fromJson(s: String): Either[Error, StringData] = decode[StringData](s)
  }

  "Inheritance ADT with identical fields" should "serialize and deserialize with Circe" in {
    val d2 = Data2("a", "b")
    val d3 = Data3("1", "2", "3")

    val jd2 = StringData.toJson(d2)
    val jd3 = StringData.toJson(d3)

    val d2Decoded = StringData.fromJson(jd2)
    val d3Decoded = StringData.fromJson(jd3)

    d2Decoded.right.get should equal(d2)
    d3Decoded.right.get should equal(d3)

    println("")
  }
问题是解码的
d3
类型始终是
Data2
类型,而不是所需的
Data3

我想出的解决方案是用这个解码器替换解码器:

    implicit val decodeData: Decoder[StringData] = Decoder.instance { c =>
      c.downField("f3").as[String] match {
        case m: Either[DecodingFailure, String] if m.isLeft => c.as[Data2]
        case m: Either[DecodingFailure, String] if m.isRight => c.as[Data3]
      }
    }
在我看来,这似乎是一个相当临时的解决办法。在Jackson中,可以将类型添加到Json中。我想知道我使用Circe的方法是否正确,或者这是否真的是正确的方法。欢迎任何评论。

尝试使用文档:

哪个输出

res0: Either[io.circe.Error,StringData] = Right(Data3(foo,bar,qux)
在哪里

res0: Either[io.circe.Error,StringData] = Right(Data3(foo,bar,qux)
libraryDependencies ++= Seq(
      "io.circe" %% "circe-core",
      "io.circe" %% "circe-generic",
      "io.circe" %% "circe-parser",
      "io.circe" %% "circe-generic-extras",
    ).map(_ % circeVersion)