2013-11-22 5 views
5

Diese Frage basiert auf dem folgenden Beispiel, bei dem versucht wird, einen Fallklassenknoten [Bird] aus JSON zu deserialisieren.Automatische Serialisierung/Deserialisierung generischer Fallklassen zu/von JSON in Play2.2 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]]] 

} 

Im vorhergehenden Beispiel ist Scala nicht in der Lage, die richtigen apply/Unapply Funktionen für Knoten [Vogel] für das Format Makro zu lösen.

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

Es gibt jedoch kein Problem mit einer nicht-generischen Fallklasse wie BirdNode.

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

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

    ... 

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

Was ist der beste Weg, so etwas wie ein Knoten zur Serialisierung/Deserialisierung [Vogel] zu/von JSON in Play 2.2?

Antwort

1

Sie können das Format für Node[T] ohne Verwendung des Makro definieren müssen, aber dies funktioniert:

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

Awesome! Stellt sich heraus, dass ich dies OHNE die Unlift-Funktion versucht habe. Als Anmerkung gibt die Funktion unapply eine Option [(arg1, arg2, ...)] zurück, und das Unlighting liefert uns die Argumente (arg1, arg2, ...), die wir für Writes benötigen. Siehe [ScalaJsonCombinators] (http://www.playframework.com/documentation/2.2.x/ScalaJsonCombinators) – johnh