Play Framework 2.4写[-A] vs OWrites [-A],格式[A] vs OFormat [A]。目的?

时间:2015-08-29 19:00:40

标签: json scala playframework-2.4

PlayFramework Json库中Writes [-A]和OWrites [-A]有什么区别?我使用过Writes [A],但我无法弄清楚OWrites的目的是什么。同样的问题适用于格式[A]与OFormat [A]。

可以找到源代码here for Writeshere for Formats。我看过他们,但我无法弄清楚他们的用法有什么不同。

1 个答案:

答案 0 :(得分:27)

通常您知道编码器将始终生成JSON对象(而不是任意JSON值)。在类型系统中跟踪这一事实使得可以使用这种编码器的输出,而无需跳过通常必要的箍。

例如,假设我们有一个简单的类:

class Foo(val name: String, val age: Long)

我们写一个这样的Writes个实例:

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

implicit val fooWrites: Writes[Foo] = (
  (__ \ 'name).write[String] and (__ \ 'age).write[Long]
)(foo => (foo.name, foo.age))

现在我们可以写下以下内容:

scala> val json = fooWrites.writes(new Foo("McBar", 101))
json: play.api.libs.json.JsValue = {"name":"McBar","age":101}

现在假设无论出于何种原因我们想要获得字段名称列表。我们必须写这样的东西:

scala> json.as[JsObject].keys
res0: scala.collection.Set[String] = Set(name, age)

而不是:

scala> json.keys
<console>:17: error: value keys is not a member of play.api.libs.json.JsValue
              json.keys
                   ^

但当然我们知道json始终是JsObject。问题是编译器没有。 OWrites解决了这个问题。

implicit val fooWrites: OWrites[Foo] = (
   (__ \ 'name).write[String] and (__ \ 'age).write[Long]
)(foo => (foo.name, foo.age))

然后:

scala> val json = fooWrites.writes(new Foo("McBar", 101))
json: play.api.libs.json.JsObject = {"name":"McBar","age":101}

scala> json.keys
res1: scala.collection.Set[String] = Set(name, age)

writesOWrites的输出被静态输入为JsObject,因此我们可以使用.keys而不使用不安全的as[JsObject]广告。

(作为旁注,我在制作方法中not personally a fan在子类中返回更具体的类型,我已经a slightly different approachcirce中解决了这个问题}。)