Как сериализовать и десериализовать рекурсивную запечатанную черту с Play Json? - PullRequest
0 голосов
/ 18 сентября 2018

Следующее дает мне ошибку переполнения стека, и я не могу понять, почему это происходит.Я также попытался сделать неявное средство форматирования для рекурсивного типа ленивым, но я получаю ту же ошибку.Есть идеи, пожалуйста?

import play.api.libs.json._
import play.api.libs.functional.syntax._

sealed trait Foo

object Foo {
  implicit val fooReads: Reads[Foo] = Reads[Foo] { json =>
    (json \ "discriminator").validate[String].flatMap {
      case "Bar" => json.validate[Bar]
      case "Baz" => json.validate[Baz]
    }
  }

  implicit val fooWrites: Writes[Foo] = Writes[Foo] {
    case bar: Bar => Json.toJson[Bar](bar)
    case baz: Baz => Json.toJson[Baz](baz)
  }
}

case class Bar(b: String) extends Foo

object Bar {
  implicit val barFormat: OFormat[Bar] = Json.format[Bar]
}

case class Baz(c: String, as: Seq[Foo]) extends Foo

object Baz {
  implicit val bazFormat: OFormat[Baz] = (
    (__ \ "c").format[String] and
      (__ \ "as").lazyFormat(implicitly[Format[Seq[Foo]]])
  )(Baz.apply, unlift(Baz.unapply))
}

val baz = Baz("aa", Seq(Baz("bb", Seq(Bar("cc")))))

Json.toJson(baz)

1 Ответ

0 голосов
/ 19 сентября 2018

Измените эту часть своего кода, чтобы явно вызывать правильные средства форматирования:

implicit val fooWrites: Writes[Foo] = Writes[Foo] {
  case bar: Bar => Json.toJson[Bar](bar)(Bar.barFormat)
  case baz: Baz => Json.toJson[Baz](baz)(Baz.bazFormat)
}

Поскольку они оба Foo s, до того как он распознал их как таковые и снова вызвал ваш fooWrites, следовательнопереполнение стека.Вы также можете посмотреть производные-json-производные кодеки , хотя я никогда не использовал его.

...