2010-11-03 10 views
6

He pasado el último día buscando y leyendo varios sitios y artículos para tratar de encontrar la respuesta a esta pregunta yo mismo y no he encontrado nada que ayude. Ni siquiera estoy seguro de si esto es factible. Mi problema es que estoy tratando de analizar y extraer una Respuesta Json utilizando lift-json. La respuesta consta de 4 partes, donde las primeras 3 partes son siempre las mismas para cada respuesta a cada tipo de solicitud que hago. La última parte varía según el tipo de solicitud, pero siempre va a ser una lista de algún tipo. Tenía la esperanza de hacer algo como esto:Extrayendo lift-json en una clase de caso con un límite superior

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

Donde si lo que quería saber lo que todas las manzanas son, me gustaría hacer una petición para eso y volver a una respuesta con una lista de las manzanas. Cuando trato de extraer este ejemplo:

myJson.extract[Fruits[Apple]] 

consigo este error:

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

estoy usando ascensor-JSON 2.1 & Scala 2.8. Tengo una forma de evitarlo, al crear específicamente una clase de caso para cada tipo de respuesta, pero pensé que lo que estaba tratando de hacer era más limpio. Solo quería saber si a) ¿es esto posible? b) si es así, ¿qué estoy haciendo mal?

aplicación EDITAR ... muestra:

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

Quiero doesntWork sea como obras, Donde:

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

Gracias! -newbie

Respuesta

8

La extracción de la clase de caso parametrizado aún no es compatible. Una solución alternativa (aunque no estoy seguro de si esto funciona para su caso) es hacer que Fruits sea un tipo concreto y agregar la información de tipo en 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) 
} 

que imprime:

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

Hola Joni, Gracias por su entrada, ¿hay algún lugar donde pueda leer sobre las diferentes configuraciones y cómo funciona la serialización? No funciona del todo. Edité mi publicación y aclaré con un ejemplo. Conseguiré cadenas como las de manzanas y naranjas y necesito terminar con algo que funcione. – CaffiendFrog

+0

Hola, los mejores recursos son este README https://github.com/lift/lift/tree/master/framework/lift-base/lift-json/ y ejemplos (* Example.scala) en https://github.com/lift/lift/tree/master/framework/lift-base/lift-json/src/test/scala/net/liftweb/json /. En este punto, no es posible hacer que funcione el caso "no funciona" en su publicación. Sin embargo, podría ser que podamos mejorar el código de reflexión en un futuro. – Joni

+0

Hola Joni, definitivamente puedo vivir con la creación de clases de casos como AFruit para respaldar lo que necesito hacer, es bueno saber que el caso 'doesntwork' no es compatible ... Ahora puedo continuar con el resto de mi tarea. :). Gracias de nuevo, y gracias especialmente por una respuesta tan rápida, muy apreciada. – CaffiendFrog

Cuestiones relacionadas