Scala Play JSON 读取 Seal Trait 或 Enum 类型对象



我有以下带有密封特征和案例对象的 scala 代码。

sealed trait StudentType {
val studentLevel: String
val code: Int
}
case object UnderGradFull extends StudentType {
val studentLevel = "UGF"
val code = 11
}
case object UnderGradPart extends StudentType {
val studentLevel = "UGP"
val code = 12
}
case object Grad extends StudentType {
val studentLevel = "GR"
val code = 22
}
case object OtherStudentType extends StudentType {
val studentLevel = "OST"
val code = 20
}

以及利用StudentType的案例类对象

case class StudentInfo(studentName: String, studentType: StudentType)
object StudentInfo {
implicit val reads: Reads[StudentInfo] = (
(JsPath  "studentName").read[String] and
(JsPath  "studentType").read[StudentType]
)(StudentInfo.apply _)
implicit val writes: Writes[StudentInfo] = (
(JsPath  "studentName").write[String] and
(JsPath  "studentType").write[StudentType]
)(unlift(StudentInfo.unapply))
}

如何为StudentType trait创建implicit reads/writes

play-json似乎对密封特征具有开箱即用的支持。分析

  • 引入该功能的拉取请求
  • 围绕密封特征的其他拉取请求
  • 显示使用情况的测试
  • 文档

似乎使用方法如下

sealed trait Family
case class ChildA(status: Boolean) extends Family
case class ChildB(name: String, age: Int) extends Family
implicit val childAFormat = Json.format[ChildA]
implicit val childBFormat = Json.format[ChildB]
implicit val familyFormat = Json.format[Family]
println(
Json.parse(
"""{
|  "name": "Bob",
|  "age": 10,
|  "_type": "controllers.ChildB"
|}""".stripMargin
).as[Family]
)

打印出ChildB(Bob,10).

play-json-extensions似乎也支持这样的密封特征

sealed trait Family
case class ChildA(status: Boolean) extends Family
case class ChildB(name: String, age: Int) extends Family
implicit val childBFormat = Jsonx.formatCaseClass[ChildB]
implicit val childAFormat = Jsonx.formatCaseClass[ChildA]
implicit val familyFormat = Jsonx.formatSealed[Family]
println(
Json.parse(
"""{
|  "name": "Bob",
|  "age": 10
|}""".stripMargin
).as[Family]
)

打印出ChildB(Bob,10).

关于案例对象,我只能在它们为空时使其工作

sealed trait Family
case object ChildA extends Family
case object ChildB extends Family
implicit val childAFormat = Json.format[ChildA.type]
implicit val childBFormat = Json.format[ChildB.type]
implicit val familyFormat = Json.format[Family]

所以我不确定如何准确解决你的问题,但希望这个答案能给出一些方向。

最新更新