9

在 Play 2.1 中,我们使用类似下面的方法通过读取从 JSON 中获取 Creature Object。

implicit val creatureReads = (
  (__ \ "name").read[String] and
  (__ \ "isDead").read[Boolean] and
  (__ \ "weight").read[Float]
)(Creature.apply _)

在 Scala 中相对较新,我试图了解是否有其他方法可以在不使用 Apply 方法的情况下构建 Creature 对象?是否可以使用匿名函数来创建对象而不是依赖应用?

我有一些用例,其中我的对象中的大多数字段都可能丢失,但我仍然想用我所拥有的来构建对象。只为对象定义一个 READ 并为每个字段使用 readnullable 会更好吗?

我也可以有复杂的条件,所以只定义自定义函数来构建它而不是试图在一个阅读器中捕获所有案例会更干净吗?

4

2 回答 2

19

是的,当然,apply 方法只是一个接受所有案例类参数的方法。这大致翻译为以下内容:

implicit val creatureReads = (
  (__ \ "name").read[String] and
  (__ \ "isDead").read[Boolean] and
  (__ \ "weight").read[Float]
)((name: String, isDead: Boolean, weight: Float) => new Creature(name, isDead, weight))

对于缺少的字段,您确实应该使用readNullable并将您的类字段包装到Option. 如果您的可选字段有合理的默认值,您可以orElse(Reads.pure(value))改用。

假设weight是可选isDead的,默认情况下为 false:

implicit val creatureReads = (
  (__ \ "name").read[String] and
  (__ \ "isDead").read[Boolean].orElse(Reads.pure(false)) and
  (__ \ "weight").readNullable[Float]
)(Creature.apply _)

有时您甚至不想从 JSON 中读取某些内容。在这种情况下,一种可能性是显式传递值:

def creatureReads(createdAt: DateTime) = (
  (__ \ "name").read[String] and
  (__ \ "isDead").read[Boolean].orElse(Reads.pure(false)) and
  (__ \ "weight").readNullable[Float] and
  (__ \ "createdAt").read(createdAt)
)(Creature.apply _)
于 2013-07-23T06:34:42.037 回答
-1

我发现这更具可读性:

implicit val createReads = new Reads[Creature] {
  override def reads(json: JsValue): JsResult[Creature] = {
    val creature = Creature(
      name = (json \ "name").as[String],
      isDead = (json \ "isDead").as[Boolean],
      weight = (json \ "weight").as[Float]
    )
    JsSuccess(creature)
  }
}
于 2014-09-10T16:51:45.953 回答