Play Framework 2.4 Writes[-A] 与 OWrites[-A]、Format[A] 与 OFormat[A]。目的?

Play Framework 2.4 Writes[-A] vs OWrites[-A], Format[A] vs OFormat[A]. Purpose?

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

可以找到源代码here for Writes and here for Formats。我看过它们,但我无法弄清楚它们在用法上的区别。

您通常知道编码器总是会生成一个 JSON 对象(与任意 JSON 值相反)。在类型系统中跟踪这一事实使得使用此类编码器的输出成为可能,而无需跳过通常需要的步骤。

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

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 of making method return types more specific in subclasses, and I've taken a slightly different approach to solving this problem in circe。)