为自定义对象创建Writes [T]

时间:2014-02-06 19:04:17

标签: json scala playframework

Play for Scala显示了如何将JSON转换为Scala对象。

case class Product(ean: Long, name: String, description: String)

    import play.api.libs.json._
    import play.api.libs.functional.syntax._

    implicit val productWrites: Writes[Product] = (
      (JsPath \ "ean").write[Long] and
      (JsPath \ "name").write[String] and
      (JsPath \ "description").write[String]
    )(unlift(Product.unapply))

然后在REPL中使用:

scala> val p = Product(100, "tilley hat", "Nice hat")
p: Product = Product(100,tilley hat,Nice hat)

scala> Json.toJson(p)
res1: play.api.libs.json.JsValue = {"ean":100,"name":"tilley hat",
                                             "description":"Nice hat"}

最后一行发生了什么:(unlift(Product.unapply))的{​​{1}}?

1 个答案:

答案 0 :(得分:4)

Product.unapply _是一个函数Product => Option[(Long, String, String)]

此表达式的结果类型:

(
  (JsPath \ "ean").write[Long] and
  (JsPath \ "name").write[String] and
  (JsPath \ "description").write[String]
)

FunctionalBuilder[OWrites]#CanBuild3[Long,String,String]。它接受T => (Long, String, String)作为方法apply的参数。

因此,您必须将Product => Option[(Long, String, String)]转换为Product => (Long, String, String)

方法unlift接受T => Option[R]并返回T => R。未提升的函数会抛出MatchError而不是None。它产生这样的东西:

val unlifted = (Product.unapply _) andThen { case Some(r) => r }

案例类的默认unapply方法永远不会返回None,因此案例类unlift是安全的。