通常您知道编码器将始终生成 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
^
但是当然we我知道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
on OWrites
静态类型为JsObject
,所以我们可以使用.keys
没有不安全的情况as[JsObject]
cast.
(作为旁注,我个人不是粉丝 https://stackoverflow.com/questions/31080332/why-is-upcasting-necessary-in-this-scala-code#comment50187425_31080332使方法返回类型在子类中更加具体,我已经采取了略有不同的方法 http://circe.github.io/circe/api/io/circe/ObjectEncoder.html来解决这个问题circe https://github.com/travisbrown/circe.)