scala Play Framework 2.4 Writes[-A] vs OWrites[-A],Format[A] vs OFormat[A].目的?

ocebsuys  于 5个月前  发布在  Scala
关注(0)|答案(1)|浏览(57)

PlayFramework Json库中Writes[-A]和OWrites[-A]有什么区别?我用过Writes[A],但我不知道OWrites的用途。同样的问题也适用于Format[A]和OFormat[A]。
可以找到here for Writeshere for Formats的源代码。我已经看过了,但我不知道它们的用法有什么区别。

wydwbb8l

wydwbb8l1#

通常,你知道编码器总是会产生一个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)


OWrites上的writes的输出是静态类型的JsObject,因此我们可以使用.keys,而无需进行不安全的as[JsObject]转换。
(As顺便说一下,我个人并不喜欢在子类中使方法返回类型更具体,我已经使用a slightly different approach来解决circe中的这个问题。

相关问题