2010-11-03 53 views
6

我花了最後一天搜索並閱讀各種網站和文章,以嘗試自己找到此問題的答案,但我沒有找到任何有用的信息。我甚至不確定這是否可行。我的問題是,我試圖使用lift-json解析和提取Json響應。該響應由4個部分組成,其中前3個部分對於我所做的每種請求的每個響應都是相同的。最後一部分取決於請求的類型,但它總是會成爲某種類型的列表。我希望做這樣的事情:將lift-json提取爲具有上限的案例類

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

在哪裏,如果我想知道所有的蘋果,我會做一個請求爲,並取回了蘋果的列表的響應。當我嘗試提取這個例子:

myJson.extract[Fruits[Apple]] 

我得到這個錯誤:

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

我使用的升降JSON 2.1 &斯卡拉2.8。我有辦法解決這個問題,特別是爲每種類型的響應創建一個case類,但是我認爲我想要做的更清晰。只是想知道如果 a)這甚至可能嗎? b)如果是這樣,我做錯了什麼?

編輯...示例應用程序:

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

我想doesntWork要像作品,其中:

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

謝謝! -newbie

回答

8

提取參數化案例類尚不支持。一種解決方法(不知道這是否適用於您的情況)是讓Fruits成爲具體類型並將類型信息添加到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) 
} 

,打印:

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

喬尼你好,謝謝你的輸入,是有沒有什麼地方我可以在不同的配置,以及如何系列化的作品讀了?它不太有效。我編輯了我的帖子並用一個例子進行了澄清。我會得到像蘋果和橘子那樣的字符串,我需要最終得到像作品一樣的東西。 – CaffiendFrog 2010-11-03 19:29:36

+0

嗨,最好的資源是https://github.com/lift/lift/tree/master/framework/lift-base/lift-json/和https://github.com上的示例(* Example.scala)/lift/lift/tree/master/framework/lift-base/lift-json/src/test/scala/net/liftweb/json /。在這一點上,你不可能在你的文章工作中做出'沒有工作'的情況。這可能是我們可以在未來改善反射代碼。 – Joni 2010-11-03 19:36:47

+0

嗨,Joni,我絕對可以生活在像AFruit這樣的案例課程中,以支持我需要做的事情,很高興知道'不工作'的案例不被支持......我現在可以繼續完成我的其餘任務。 :)。再次感謝,特別感謝這麼快的迴應,非常感謝。 – CaffiendFrog 2010-11-03 19:43:38