使用密封特征/案例类播放JSON:无限递归

时间:2018-08-31 00:30:42

标签: scala playframework traits case-class play-json

我有一个代码,在其中尝试通过为基本特征定义自定义Writes来自定义一堆case类的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))

2 个答案:

答案 0 :(得分:3)

这应该做到:

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之前,栈就溢出了。

答案 1 :(得分:1)

您需要 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