玩 JSON with sealed trait / case 类: 无限递归

Play JSON with sealed trait / case classes: infinite recursion

我有一个代码,我尝试通过为基本特征定义自定义 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._

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))

诀窍是显式添加 teacherWritesstudentWrites。因为它们都是 Person,所以在识别它们并再次调用您的 personWrites 之前,因此堆栈溢出。

你需要play-json-derived-codecs

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