1

我理解 Play 中 Json 组合器的优点之一是您可以使用相同的模型,但通过使用不同的 Writes 组合器来生成不同的 json 格式。今天我找到了一个用例,但似乎无法让它工作。

case class Person(firstName: String, lastName: String, city: String)

object Person {
  implicit val writes = (
    (__ \ "firstName").write[String] ~
    (__ \ "lastName").write[String] ~
    (__ \ "city").write[String])(unlift(Person.unapply))

  val cityWrites = (
    (__ \ "city").write[String])(unlift(Person.unapply))
}

上面的定义给了我编译错误,因为 nameWrites 与案例类定义不匹配。我可能可以创建一个构造函数覆盖 (this(lastName: String)),但它对模型类没有意义。第二个 Json 的目的只是为了看看我们在哪些城市有客户。

我可以影响这里的 unlift 操作吗?我似乎无法找到有关它的文档。

4

2 回答 2

1

我和你一样在黑暗中unlift(),但从它的类型签名来看:

def unlift[A, B](f : (A) => Option[B]) : (A) => B

它似乎想要一个Option在您尝试编写的字段周围返回 an 的函数。所以:

val cityWrites = (
  (__ \ "city").write[String])
  (unlift( (p:Person) => Some(p.city)) )

应该解决这个问题cityWrites

实际上,只是弄乱这些东西,我可以做一个nameWrites(我猜你想把名字和姓氏写成 JSON)而不使用unapply

val nameWrites = (
  (__ \ "firstName").write[String] ~
  (__ \ "lastName").write[String])( (p:Person) => (p.firstName, p.lastName) )

我认为这看起来也很清楚。

编辑:以下是如何使用它implicit来编写Person对象列表:

object Person {
  val nameWrites = (
    (__ \ "firstName").write[String] and
    (__ \ "lastName").write[String])( (p:Person) => (p.firstName, p.lastName) )
}

...

val p1 = Person("John", "Smith", "Dallas")
val p2 = Person("Bob", "Smith", "Dallas")
val p3 = Person("Tom", "Smith", "Dallas")

val personList = List(p1, p2, p3)

implicit val nWrites: Writes[Person] = Person.nameWrites

println(Json.toJson(personList))
于 2013-11-08T06:01:12.867 回答
1

那我会去的:

val cityWrites: Writes[Person] = new Writes[Person] {
  def writes(o: Person) = JsString(o.city)
}

然后使用它:

val serialized = Json.toJson(List[Person]())(Writes.list(cityWrites))

不过,我相信在这种情况下最好的是,因为它不包含重复项:

Json.toJson(List[Person]().map(_.city).distinct)

但我猜你想用格式来播放它,对吧?

于 2013-11-08T09:54:30.480 回答