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}}?
答案 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
是安全的。