繁体   English   中英

在Play中将Seq映射到JSON

[英]Mapping Seq to JSON in Play

我正在尝试使用Play 2.x将Scala案例类映射到JSON。 这适用于案例类的简单版本,但是当涉及到Seq或对象列表时则不适用:然后我得到“无隐式格式”和“找不到未应用函数”错误。

我正在使用的代码如下:

case class Book(title: String, authors: Seq[Author])
case class Author(name: String)

我已经使用Json.format宏为此生成读取和写入:

implicit val bookFormat = Json.format[Book]
implicit val authorFormat = Json.format[Author]

但是现在当我编译代码时,我收到以下错误:

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]
                                        ^

没有Seq它可以很好地工作,但是使用Seq,它会失败。 我尝试将implicit val authorsFormat = Json.format[Seq[Author]]到隐式转换器,但这没有任何效果。

为需要序列化的图中的每个类定义遵循其依赖顺序的格式化程序。

格式化Book需要格式化Author ,因此在Book格式化程序之前定义Author格式化程序。

例如,使用此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]
}

和这个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)
  }

}

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"}]}]

对于更高级的格式化,包括部分序列化以避免必须为不应序列化的类声明格式化程序,请参阅JSON读取/写入/格式化组合器

应该记住,要序列化的类不一定必须是域模型类。 声明反映所需JSON结构的数据传输对象(DTO)类并从域模型实例化它们可能会有所帮助。 这样,使用Json.format可以直接进行序列化,并且不存在部分序列化的问题,并且具有JSON API的类型安全表示的额外好处。

例如,此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]

}

这个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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM