Definieren Sie die Formatierer unter Berücksichtigung ihrer Abhängigkeitsreihenfolge für jede Klasse im Diagramm, die serialisiert werden muss.
Formatierung Book
erfordert Formatierung Author
, so definieren Sie den Author
Formatierer vor dem Book
Formatierer.
Zum Beispiel mit dieser Models.scala
Datei:
package models
import play.api.libs.json._
case class Book(title: String, authors: Seq[Author])
case class Author(name: String)
object Formatters {
implicit val authorFormat = Json.format[Author]
implicit val bookFormat = Json.format[Book]
}
und diese JsonExample.scala
Datei:
package controllers
import models._
import models.Formatters._
import play.api.mvc._
import play.api.libs.json._
object JsonExample extends Controller {
def listBooks = Action {
val books = Seq(
Book("Book One", Seq(Author("Author One"))),
Book("Book Two", Seq(Author("Author One"), Author("Author Two")))
)
val json = Json.toJson(books)
Ok(json)
}
}
eine Anfrage an listBooks
wird dieses Ergebnis produzieren:
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Content-Length: 133
<
[{"title":"Book One","authors":[{"name":"Author One"}]},{"title":"Book Two","authors":[{"name":"Author One"},{"name":"Author Two"}]}]
Für fortgeschrittenere Formatierung, einschließlich partieller Serialisierung zu Avo ID muss Formatierer für Klassen deklarieren, die nicht serialisiert werden sollten, siehe JSON Reads/Writes/Format Combinators.
Es sollte berücksichtigt werden, dass die zu serialisierenden Klassen nicht notwendigerweise die Domänenmodellklassen sein müssen. Es kann hilfreich sein, Datenübertragungsobjektklassen (DTO-Klassen) zu deklarieren, die die gewünschte JSON-Struktur widerspiegeln, und diese aus dem Domänenmodell zu instanziieren. Auf diese Weise ist Serialisierung mit Json.format
unkompliziert und es gibt nicht das Problem der partiellen Serialisierung, mit dem zusätzlichen Vorteil einer typsicheren Darstellung der JSON-API.
Zum Beispiel dieser BookDTO.scala
Datei definiert ein BookDTO
Datenübertragungsobjekt, das nur Typen verwendet, die ohne weitere Definition zu JSON serialisiert werden können:
package dtos
import models._
import play.api.libs.json.Json
case class BookDTO (title: String, authors: Seq[String])
object BookDTO {
def fromBook(b: Book) = BookDTO(b.title, b.authors.map(_.name))
implicit val bookDTOFormat = Json.format[BookDTO]
}
und diese JsonExample2.scala
Datei zeigt, wie dieses Muster verwenden:
package controllers
import dtos._
import dtos.BookDTO._
import models._
import play.api.mvc._
import play.api.libs.json._
import play.api.libs.functional.syntax._
object JsonExample2 extends Controller {
def listBooks = Action {
val books = Seq(
Book("Book One", Seq(Author("Author One"))),
Book("Book Two", Seq(Author("Author One"), Author("Author Two")))
)
val booksDTO = books.map(BookDTO.fromBook(_))
Ok(Json.toJson(booksDTO))
}
}
sie in umgekehrter Reihenfolge definieren funktionieren sollte: implizite val authorformat = Json.format [Autor] implizite val bookFormat = Json.fo rmat [Buch] –
Wow, das habe ich vermisst. Vielen Dank! Übrigens, haben Sie auch einen Vorschlag, diese Liste nicht weiter zu erweitern? Muss ich wirklich ein Json.format für jede Fallklasse manuell registrieren? –