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

vic*_*aba 21 json scala playframework-2.4

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

源代码可以在这里找到Writes,这里可以找到Formats.我看过他们,但我无法弄清楚他们的用法有何不同.

Tra*_*own 29

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

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

class Foo(val name: String, val age: Long)
Run Code Online (Sandbox Code Playgroud)

我们写一个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))
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

而不是这个:

scala> json.keys
<console>:17: error: value keys is not a member of play.api.libs.json.JsValue
              json.keys
                   ^
Run Code Online (Sandbox Code Playgroud)

我们当然知道这json将永远是一个JsObject.问题是编译器没有.OWrites解决这个问题.

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

然后:

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)
Run Code Online (Sandbox Code Playgroud)

writeson 的输出OWrites静态类型为a JsObject,因此我们可以在.keys没有不安全的as[JsObject]强制转换的情况下使用.

(作为旁注,我个人并不喜欢在子类中使方法返回类型更具体,并且我采用了稍微不同的方法来解决这个问题.)