2010-11-03 5 views
6

J'ai passé le dernier jour à chercher et lire divers sites et articles pour essayer de trouver la réponse à cette question moi-même et je n'ai rien trouvé qui aide. Je ne suis même pas sûr que ce soit faisable. Mon problème est que j'essaye d'analyser et d'extraire une réponse de Json en utilisant lift-json. La réponse se compose de 4 parties, où les 3 premières parties sont toujours les mêmes pour chaque réponse à chaque type de requête que je fais. La dernière partie varie en fonction du type de requête, mais il s'agira toujours d'une liste de type. J'espérais faire quelque chose comme ceci:Extraire lift-json dans une classe de cas avec une limite supérieure

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]]) 

Où si je voulais savoir ce que toutes les pommes sont, je voudrais faire une demande pour cela et retourner une réponse avec une liste de pommes. Lorsque je tente d'extraire cet exemple:

myJson.extract[Fruits[Apple]] 

Je reçois cette erreur:

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:... 

J'utilise relevable JSON 2.1 & scala 2.8. J'ai un moyen de contourner cela, en créant spécifiquement une classe de cas pour chaque type de réponse, mais je pensais que ce que j'essayais de faire était plus propre. Je voulais juste savoir si a) est-ce encore possible? b) si oui, qu'est-ce que je fais de mal?

EDIT ... exemple d'application:

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)))) 

Je veux être comme nefonctionnepas œuvres, Où:

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

Merci! -newbie

Répondre

8

L'extraction de la classe de cas paramétrée n'est pas encore prise en charge. Une solution de contournement (pas sûr si cela fonctionne pour votre cas cependant) est de faire un type concret de Fruits et d'ajouter les informations de type dans JSON.

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) 
} 

qui imprime:

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

Salut Joni, Nous vous remercions de votre entrée, est là où je peux lire sur les différentes configurations et le fonctionnement de sérialisation? Ça ne marche pas vraiment. J'ai édité mon post et clarifié avec un exemple. Je vais avoir des ficelles comme celles pour les pommes et les oranges et je dois finir avec quelque chose qui ressemble à des œuvres. – CaffiendFrog

+0

Salut, les meilleures ressources sont ce README https://github.com/lift/lift/tree/master/framework/lift-base/lift-json/ et des exemples (* Example.scala) dans https://github.com/ascenseur/ascenseur/arbre/maître/charpente/élévateur/ascenseur-json/src/test/scala/filet/bande de levage/json /. À ce stade, il n'est pas possible de faire un cas de «doesntwork» dans votre poste de travail. Il se pourrait que nous puissions améliorer le code de réflexion dans un futur. – Joni

+0

Salut Joni, je peux vraiment vivre avec des classes de cas comme AFruit pour supporter ce que j'ai besoin de faire, bon de savoir que le cas 'doesntwork' n'est pas supporté ... Je peux maintenant continuer avec le reste de ma tâche. :) Merci encore, et surtout merci pour une réponse si rapide, extrêmement appréciée. – CaffiendFrog

Questions connexes