使用密封的特征/案例类播放JSON:无限递归
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用密封的特征/案例类播放JSON:无限递归相关的知识,希望对你有一定的参考价值。
我有一个代码,我尝试通过为基本特征定义自定义Writes来自定义一堆案例类的JSON序列化。我得到无限递归/堆栈溢出。
我创建了一个简化的示例 - 如果有人知道如何解决它,请告诉我。
import play.api.libs.json._
sealed trait Person {
val name: String
}
final case class Teacher(name: String, salary: Int) extends Person
final case class Student(name: String, grade: Int) extends Person
implicit val teacherWrites: Writes[Teacher] = Json.writes[Teacher]
implicit val studentWrites: Writes[Student] = Json.writes[Student]
val ThePersonWrites: Writes[Person] = Writes(person => {
Json.writes[Person].writes(person).as[JsObject] - "_type"
})
implicit val personWrites: Writes[Person] = ThePersonWrites
val people = List[Person] (
Teacher("Jane Doe", 40000),
Student("Alice", 5),
Student("Bob", 7)
)
Json.prettyPrint(Json.toJson(people))
答案
import play.api.libs.json._
import julienrf.json.derived
sealed trait Person {
val name: String
}
object Person {
implicit val jsonFormat: OFormat[Person] = derived.oformat[Person]()
}
final case class Teacher(name: String, salary: Int) extends Person
final case class Student(name: String, grade: Int) extends Person
val people = List[Person] (
Teacher("Jane Doe", 40000),
Student("Alice", 5),
Student("Bob", 7)
)
println(Json.prettyPrint(Json.toJson(people)))
在这里看到scalafiddle
另一答案
这应该这样做:
import play.api.libs.json._
sealed trait Person {
val name: String
}
final case class Teacher(name: String, salary: Int) extends Person
final case class Student(name: String, grade: Int) extends Person
implicit val teacherWrites: Writes[Teacher] = Json.writes[Teacher]
implicit val studentWrites: Writes[Student] = Json.writes[Student]
implicit val personWrites: Writes[Person] = Writes[Person] {
case t: Teacher => Json.toJson(t)(teacherWrites)
case s: Student => Json.toJson(s)(studentWrites)
}
val people = List[Person] (
Teacher("Jane Doe", 40000),
Student("Alice", 5),
Student("Bob", 7)
)
Json.prettyPrint(Json.toJson(people))
诀窍是明确添加teacherWrites
和studentWrites
。因为它们都是Person
s,在它们识别它们之前再次调用你的personWrites
,因此堆栈溢出。
以上是关于使用密封的特征/案例类播放JSON:无限递归的主要内容,如果未能解决你的问题,请参考以下文章
带有 Play 2.2 库的密封特征的无噪声 JSON 格式
抽象类上的 Json.reads(不支持密封特征:没有已知的子类)