[英]Mapping Seq to JSON in Play
I'm trying to map a Scala case class to JSON using Play 2.x. 我正在尝试使用Play 2.x将Scala案例类映射到JSON。 This works for simple versions of the case class, but not when there's a Seq or List of objects involved: then I get 'no implicit format' and 'no unapply function found' errors.
这适用于案例类的简单版本,但是当涉及到Seq或对象列表时则不适用:然后我得到“无隐式格式”和“找不到未应用函数”错误。
The code I'm using for this is the following: 我正在使用的代码如下:
case class Book(title: String, authors: Seq[Author])
case class Author(name: String)
I've used the Json.format
macro to generate the Reads and Writes for this: 我已经使用
Json.format
宏为此生成读取和写入:
implicit val bookFormat = Json.format[Book]
implicit val authorFormat = Json.format[Author]
But now when I'm compiling my code, I get the following error: 但是现在当我编译代码时,我收到以下错误:
Error:(25, 40) Play 2 Compiler:
/Users/erikp/Userfiles/projects/play/booksearch/app/models/user.scala:25: No implicit format for Seq[models.Author] available.
implicit val bookFormat = Json.format[Book]
^
Without the Seq it works nicely, but with the Seq, it fails. 没有Seq它可以很好地工作,但是使用Seq,它会失败。 I tried adding
implicit val authorsFormat = Json.format[Seq[Author]]
to the implicit converters, but that has no effect. 我尝试将
implicit val authorsFormat = Json.format[Seq[Author]]
到隐式转换器,但这没有任何效果。
Define the formatters respecting their dependency order, for each class in the graph that needs to be serialized. 为需要序列化的图中的每个类定义遵循其依赖顺序的格式化程序。
Formatting Book
requires formatting Author
, so define the Author
formatter before the Book
formatter. 格式化
Book
需要格式化Author
,因此在Book
格式化程序之前定义Author
格式化程序。
For example, with this Models.scala
file: 例如,使用此
Models.scala
文件:
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]
}
and this JsonExample.scala
file: 和这个
JsonExample.scala
文件:
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)
}
}
a request to listBooks
will produce this result: listBooks
的请求将产生以下结果:
< 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"}]}]
For more advanced formatting, including partial serialization to avoid having to declare formatters for classes that should not be serialized, see JSON Reads/Writes/Format Combinators . 对于更高级的格式化,包括部分序列化以避免必须为不应序列化的类声明格式化程序,请参阅JSON读取/写入/格式化组合器 。
It should be kept in mind that the classes to be serialized don't necessarily have to be the domain model classes. 应该记住,要序列化的类不一定必须是域模型类。 It may be helpful to declare data transfer object (DTO) classes that reflect the desired JSON structure, and instantiate them from the domain model.
声明反映所需JSON结构的数据传输对象(DTO)类并从域模型实例化它们可能会有所帮助。 This way, serialization is straightforward with
Json.format
and there isn't the issue of partial serialization, with the added benefit of a typesafe representation of the JSON API. 这样,使用
Json.format
可以直接进行序列化,并且不存在部分序列化的问题,并且具有JSON API的类型安全表示的额外好处。
For example, this BookDTO.scala
file defines a BookDTO
data transfer object that uses only types that can be serialized to JSON without requiring further definition: 例如,此
BookDTO.scala
文件定义了BookDTO
数据传输对象,该对象仅使用可以序列化为JSON的类型,而无需进一步定义:
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]
}
and this JsonExample2.scala
file shows how to use this pattern: 这个
JsonExample2.scala
文件显示了如何使用这个模式:
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))
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.