Circe 解码为由多个案例扩展的密封特征 类
Circe Decode to sealed trait extended by multiple case classes
我以前见过类似的问题,但 none 已经解决了。我认为他们问的是不同的东西,所以我在这里问。
我在一个文件中有这样的东西:
sealed trait Thing
case class SomeThing() extends Thing
case class OtherThing() extends Thing
在另一个文件中:
val str = //valid json
val decoded = decode[Thing](str)
println(decoded)
我得到:
Left(DecodingFailure(...))
如果我这样做了,这会起作用:
val str = //valid json
val decoded = decode[SomeThing](str)
println(decoded)
看起来你可以 运行 变成 this known issue。
根据那里的讨论,也许你可以试试:
import io.circe.generic.JsonCodec
@JsonCodec sealed trait Thing
case class SomeThing() extends Thing
case class OtherThing() extends Thing
object Thing
我不得不为 serialization/deserialization 编写自己的编码器和解码器。
示例,
import io.circe._, io.circe.generic.auto._, io.circe.parser._, io.circe.syntax._
object CirceSubtypesSerialisers {
def main(args: Array[String]): Unit = {
sealed trait Data
case class OptionsData(data: Seq[String]) extends Data
case class TextData(data: String) extends Data
object Data {
implicit val decodeData: Decoder[Data] = Decoder[OptionsData].map[Data](identity).or(Decoder[TextData].map[Data](identity))
implicit val encodeData: Encoder[Data] = Encoder.instance {
case options @ OptionsData(_) => options.asJson
case text @ TextData(_) => text.asJson
}
}
val optionsJson ="""{ "data": ["option1", "option2"] }""".stripMargin
decode[Data](optionsJson) match {
case Right(r: OptionsData) => println(r)
case Left(l) => println(l)
}
val textJson ="""{ "data": "hey, how can i help ya?" }""".stripMargin
decode[Data](textJson) match {
case Right(r: TextData) => println(r)
case Left(l) => println(l)
}
}
}
输出:
OptionsData(List(option1, option2))
TextData(hey, how can i help ya?)
这个在https://circe.github.io/circe/codec.html#warnings-and-known-issues and JsonCodec for sealed traits requires an explicit object definition
中也有提到
您可以使用 circe-generic-extras 并为您的 json 添加类型鉴别器:
在你的build.sbt中:
libraryDependencies ++= Seq(
"io.circe" %% "circe-generic-extras" % "0.12.2",
"io.circe" %% "circe-parser" % "0.12.2"
)
现在让我们定义 classes 并序列化和反序列化它们:
sealed trait Thing
case class SomeThing() extends Thing
case class OtherThing() extends Thing
import io.circe.generic.extras.auto._
import io.circe.generic.extras.Configuration
import io.circe.syntax._
import io.circe.parser
implicit val customConfig: Configuration =
Configuration.default.withSnakeCaseMemberNames.withDiscriminator("type")
val thing: Thing = SomeThing()
// serialize thing to json
val jsString: String = thing.asJson.spaces2
println(s"serialized $thing to:\n$jsString")
/* serialized SomeThing() to:
{
"type" : "SomeThing"
}
*/
// deserialize json to thing
val errorOrMyTrait: Either[io.circe.Error, Thing] = parser.decode[Thing](jsString)
println(errorOrMyTrait) // Right(SomeThing())
注意现在序列化的 json 包含密封的类型 class
我以前见过类似的问题,但 none 已经解决了。我认为他们问的是不同的东西,所以我在这里问。 我在一个文件中有这样的东西:
sealed trait Thing
case class SomeThing() extends Thing
case class OtherThing() extends Thing
在另一个文件中:
val str = //valid json
val decoded = decode[Thing](str)
println(decoded)
我得到:
Left(DecodingFailure(...))
如果我这样做了,这会起作用:
val str = //valid json
val decoded = decode[SomeThing](str)
println(decoded)
看起来你可以 运行 变成 this known issue。
根据那里的讨论,也许你可以试试:
import io.circe.generic.JsonCodec
@JsonCodec sealed trait Thing
case class SomeThing() extends Thing
case class OtherThing() extends Thing
object Thing
我不得不为 serialization/deserialization 编写自己的编码器和解码器。
示例,
import io.circe._, io.circe.generic.auto._, io.circe.parser._, io.circe.syntax._
object CirceSubtypesSerialisers {
def main(args: Array[String]): Unit = {
sealed trait Data
case class OptionsData(data: Seq[String]) extends Data
case class TextData(data: String) extends Data
object Data {
implicit val decodeData: Decoder[Data] = Decoder[OptionsData].map[Data](identity).or(Decoder[TextData].map[Data](identity))
implicit val encodeData: Encoder[Data] = Encoder.instance {
case options @ OptionsData(_) => options.asJson
case text @ TextData(_) => text.asJson
}
}
val optionsJson ="""{ "data": ["option1", "option2"] }""".stripMargin
decode[Data](optionsJson) match {
case Right(r: OptionsData) => println(r)
case Left(l) => println(l)
}
val textJson ="""{ "data": "hey, how can i help ya?" }""".stripMargin
decode[Data](textJson) match {
case Right(r: TextData) => println(r)
case Left(l) => println(l)
}
}
}
输出:
OptionsData(List(option1, option2))
TextData(hey, how can i help ya?)
这个在https://circe.github.io/circe/codec.html#warnings-and-known-issues and JsonCodec for sealed traits requires an explicit object definition
中也有提到您可以使用 circe-generic-extras 并为您的 json 添加类型鉴别器:
在你的build.sbt中:
libraryDependencies ++= Seq(
"io.circe" %% "circe-generic-extras" % "0.12.2",
"io.circe" %% "circe-parser" % "0.12.2"
)
现在让我们定义 classes 并序列化和反序列化它们:
sealed trait Thing
case class SomeThing() extends Thing
case class OtherThing() extends Thing
import io.circe.generic.extras.auto._
import io.circe.generic.extras.Configuration
import io.circe.syntax._
import io.circe.parser
implicit val customConfig: Configuration =
Configuration.default.withSnakeCaseMemberNames.withDiscriminator("type")
val thing: Thing = SomeThing()
// serialize thing to json
val jsString: String = thing.asJson.spaces2
println(s"serialized $thing to:\n$jsString")
/* serialized SomeThing() to:
{
"type" : "SomeThing"
}
*/
// deserialize json to thing
val errorOrMyTrait: Either[io.circe.Error, Thing] = parser.decode[Thing](jsString)
println(errorOrMyTrait) // Right(SomeThing())
注意现在序列化的 json 包含密封的类型 class