PlayFramework Json库中Writes [-A]和OWrites [-A]有什么区别?我使用过Writes [A],但我无法弄清楚OWrites的目的是什么。同样的问题适用于格式[A]与OFormat [A]。
可以找到源代码here for Writes和here for Formats。我看过他们,但我无法弄清楚他们的用法有什么不同。
答案 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)
writes
上OWrites
的输出被静态输入为JsObject
,因此我们可以使用.keys
而不使用不安全的as[JsObject]
广告。
(作为旁注,我在制作方法中not personally a fan在子类中返回更具体的类型,我已经a slightly different approach在circe中解决了这个问题}。)