2010-11-03 12 views
6

Ich habe den letzten Tag damit verbracht, verschiedene Seiten und Artikel zu suchen und zu lesen, um die Antwort auf diese Frage selbst zu finden, und ich habe nichts gefunden, was hilft. Ich bin mir nicht einmal sicher, ob das machbar ist. Mein Problem ist, dass ich versuche, eine Json-Antwort mit Lift-Json zu analysieren und zu extrahieren. Die Antwort besteht aus 4 Teilen, wobei die ersten 3 Teile immer gleich sind für jede Antwort auf jede Art von Anfrage, die ich mache. Der letzte Teil hängt von der Art der Anfrage ab, aber es wird immer eine Liste eines Typs sein. Ich habe gehofft, so etwas zu tun:Lift-JSON in eine Fallklasse mit einer Obergrenze extrahieren

abstract class MyObjects 
case class Apple(id: Int, name: String, color: String) extends MyObjects 
case class Orange(id: Long, name: String, state: String) extends MyObjects 

abstract class MyResponse 
case class Fruits[T <: MyObjects](aisle: Int, bin: Int, hasWhat: Option[List[T]]) 

Wo, wenn ich wollte wissen, was all die Äpfel sind, würde ich eine Anfrage für das machen und eine Antwort mit einer Liste von Äpfeln zurück. Wenn ich versuche, dieses Beispiel zu extrahieren:

myJson.extract[Fruits[Apple]] 

ich diesen Fehler:

net.liftweb.json.MappingException: do not know how to get type parameter from T 
    at net.liftweb.json.Meta$.fail(Meta.scala:128) 
    at net.liftweb.json.Meta$Reflection$.term$1(Meta.scala:206) 
    at net.liftweb.json.Meta$Reflection$.typeParameters(Meta.scala:220) 
    at net.liftweb.json.Meta$.mkContainer$1(Meta.scala:91) 
    at net.liftweb.json.Meta$.fieldMapping$1(Meta.scala:101) 
    at net.liftweb.json.Meta$.mkContainer$1(Meta.scala:90) 
    at net.liftweb.json.Meta$.fieldMapping$1(Meta.scala:107) 
    at net.liftweb.json.Meta$.toArg$1(Meta.scala:117) 
    at net.liftweb.json.Meta$$anonfun$constructors$1$1$$anonfun$apply$1.apply(Meta.scala:83) 
    at net.liftweb.json.Meta$$anonfun$constructors$1$1$$anonfun$apply$1.apply(Meta.scala:82) 
    at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:... 

Ich bin mit Lift-json 2.1 & scala 2.8. Ich habe einen Weg, um es zu umgehen, indem ich für jeden Antworttyp spezifisch eine Fallklasse erstelle, aber ich dachte, was ich zu tun versuche, war sauberer. Wollte nur wissen, ob a) ist das überhaupt möglich? b) Wenn ja, was mache ich falsch?

EDIT ... Beispielanwendung:

val apples = """{ "aisle" : 1, "bin" : 1, 
      "hasWhat" : [{ "id" : 4, "name" : "Granny", "color" : "green"}, 
         { "id" : 4, "name" : "Fuji", "color" : "red"}] }""" 

val oranges = """ { "aisle" : 3, "bin" : 2, 
      "hasWhat" : [{ "id" : 2, "name" : "Navel", "state" : "FL" }, 
         { "id" : 2, "name" : "Clementine", "state" : "Spain" }]}""" 

scala> val aJson = parse(apples) 
aJson: net.liftweb.json.JsonAST.JValue = JObject(List(JField(aisle,JInt(1)), JField(bin,JInt(1)), JField(hasWhat,JArray(List(JObject(List(JField(id,JInt(4)), JField(name,JString(Granny)), JField(color,JString(green)))), JObject(List(JField(id,JInt(4)), JField(name,JString(Fuji)), JField(color,JString(red))))))))) 

scala> val oJson = parse(oranges) 
oJson: net.liftweb.json.JsonAST.JValue = JObject(List(JField(aisle,JInt(3)), JField(bin,JInt(2)), JField(hasWhat,JArray(List(JObject(List(JField(id,JInt(2)), JField(name,JString(Navel)), JField(state,JString(FL))))))))) 

scala> val doesntWork = aJson.extract[Fruits] 
doesntWork: org.spin.node.gogrid.objects.Fruits = Fruits(1,1,None) 

scala> val works = aJson.extract[AFruit] 
works: org.spin.node.gogrid.objects.AFruit = AFruit(1,1,Some(List(Apple(4,Granny,green), Apple(4,Fuji,red)))) 

Ich möchte doesntWork wie Werk, wo:

case class AFruit(aisle: Int, bin: Int, hasWhat: Option[List[Apple]]) 

Dank! -newbie

Antwort

8

Das Extrahieren der parametrisierten Fallklasse wird noch nicht unterstützt. Eine Problemumgehung (nicht sicher, ob das für Ihren Fall funktioniert) besteht darin, Fruits zu einem konkreten Typ zu machen und die Typinformationen in JSON hinzuzufügen.

import net.liftweb.json._ 
import net.liftweb.json.Extraction._ 
import net.liftweb.json.JsonAST._ 
import net.liftweb.json.Printer._ 

abstract class MyObjects 
case class Apple(id: Int, name: String, color: String) extends MyObjects 
case class Orange(id: Long, name: String, state: String) extends MyObjects 

case class Fruits(aisle: Int, bin: Int, hasWhat: Option[List[MyObjects]]) 

object Test extends Application { 
    // This configuration adds an extra field for MyObjects to JSON 
    // which tells the real type of a MyObject. 
    implicit val formats = Serialization.formats(FullTypeHints(List(classOf[MyObjects]))) 

    val fs = Fruits(0, 0, Some(List(
    Apple(1, "Granny Smith", "green"), 
    Apple(2, "Grenade", "red")))) 
    val json = decompose(fs) 
    println(pretty(render(json))) 

    assert (json.extract[Fruits] == fs) 
} 

die Drucke:

{ 
    "aisle":0, 
    "bin":0, 
    "hasWhat":[{ 
    "jsonClass":"Apple", 
    "id":1, 
    "name":"Granny Smith", 
    "color":"green" 
    },{ 
    "jsonClass":"Apple", 
    "id":2, 
    "name":"Grenade", 
    "color":"red" 
    }] 
} 
+0

Hallo Joni, Vielen Dank für Ihre Eingabe, gibt es überall, wo ich auf die verschiedenen Konfigurationen lesen kann und wie die Serialisierung funktioniert? Es funktioniert nicht ganz. Ich habe meinen Beitrag bearbeitet und mit einem Beispiel geklärt. Ich werde Saiten wie für Äpfel und Orangen bekommen und ich muss mit etwas enden, das wie Werke ist. – CaffiendFrog

+0

Hallo, beste Ressourcen sind diese README https://github.com/lift/lift/tree/master/framework/lift-base/lift-json/ und Beispiele (* Example.scala) in https://github.com/heben/heben/baum/master/framework/lift-base/lift-json/src/test/scala/netz/liftweb/json /. An dieser Stelle ist es nicht möglich, in Ihrem Post-Working-Vorgang "doesntwork" zu machen. Es könnte sein, dass wir den Reflektionscode in Zukunft verbessern können. – Joni

+0

Hallo Joni, ich kann definitiv mit Fallklassen wie AFruit leben, um zu unterstützen, was ich tun muss, gut zu wissen, dass der 'doesntwork' Fall nicht unterstützt wird ... Ich kann jetzt mit dem Rest meiner Aufgabe fortfahren. :). Danke nochmal, und danke besonders für so eine schnelle Antwort, sehr geschätzt. – CaffiendFrog

Verwandte Themen