Играть в JSON с запечатанными классами черт / кейсов: бесконечная рекурсия - PullRequest
0 голосов
/ 31 августа 2018

У меня есть код, в котором я пытаюсь настроить сериализацию 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 голосов
/ 31 августа 2018

Вам нужно производные от json-кодеки

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

0 голосов
/ 31 августа 2018

Это должно сделать это:

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, следовательно, переполнение стека.

...