2013-11-22 73 views
5

此問題基於以下示例,該示例嘗試從JSON反序列化案例類Node [Bird]。在Play2.2中將JSON的泛型案例類自動序列化/反序列化Scala

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

object ValidationTest { 

    case class Node[T](_id: Int, thing: T) 

    case class Bird(name: String, color: String) 

    // ERROR -- No apply function found matching unapply parameters 
    implicit val birdNodeFormat = Json.format[Node[Bird]] 

    val birdNodesJson: JsValue = Json.arr(
    Json.obj(
     "_id" -> 0, 
     "thing" -> Json.obj(
      "name" -> "Cardinal", 
      "color" -> "Red" 
    ) 
    ), 
    Json.obj(
     "_id" -> 1, 
     "thing" -> Json.obj(
     "name" -> "Bluejay", 
     "color" -> "Blue" 
    ) 
    ) 
) 

    val birdNodesResult = birdNodesJson.validate[Seq[Node[Bird]]] 

} 

在上例中,Scala無法爲格式宏解析Node [Bird]的正確apply/unapply函數。

// ERROR -- No apply function found matching unapply parameters 
    implicit val birdNodeFormat = Json.format[Node[Bird]] 

但是,使用諸如BirdNode之類的非泛型事例類沒有問題。

case class BirdNode(_id: Int, thing: Bird) 

    // WORKS 
    implicit val birdNodeFormat = Json.format[BirdNode] 

    ... 

    // WORKS 
    val birdNodesResult = birdNodesJson.validate[Seq[BirdNode]] 

什麼是序列化/反序列化的東西像播放2.2中的JSON的節點[鳥] /最好的方法是什麼?

回答

1

您可能需要定義格式Node[T]不使用宏,但這個工程:

implicit val birdFormat: Format[Bird] = Json.format[Bird] 

implicit def nodeFormat[T : Format]: Format[Node[T]] = 
    ((__ \ "_id").format[Int] ~ 
    (__ \ "thing").format[T] 
)(Node.apply, unlift(Node.unapply)) 
+0

真棒!原來,我沒有使用unlift函數嘗試過。需要注意的是,unapply函數返回一個Option [(arg1,arg2,...)]並解除它提供我們所需的Writes的(arg1,arg2,...)。參見[ScalaJsonCombinators](http://www.playframework.com/documentation/2.2.x/ScalaJsonCombinators) – johnh