我花了最后一天搜索和阅读各种网站和文章,试图找到这个问题的答案,我没有发现任何有用的东西。我甚至不确定这是否可行。我的问题是我试图使用lift-json解析并提取Json响应。响应由4部分组成,其中前3个部分对于我所做的每种类型的请求的每个响应总是相同的。最后一部分取决于请求的类型,但它总是一个类型的列表。我希望能做到这样的事情:
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:...
我正在使用lift-json 2.1&amp;斯卡拉2.8。我确实有办法解决它,通过专门为每种类型的响应创建一个案例类,但我认为我想要做的更干净。只是想知道是否 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))))
我希望dontWork能像作品一样,在哪里:
case class AFruit(aisle: Int, bin: Int, hasWhat: Option[List[Apple]])
谢谢! -newbie
答案 0 :(得分: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"
}]
}