将 lift-json 提取到具有上限的案例类中
我花了最后一天的时间搜索和阅读各种网站和文章,试图自己找到这个问题的答案,但我没有找到任何有帮助的东西。我什至不确定这是否可行。我的问题是我正在尝试使用 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 &斯卡拉 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))))
我希望 isntWork 就像 Works 一样,其中:
case class AFruit(aisle: Int, bin: Int, hasWhat: Option[List[Apple]])
谢谢! -新手
I have spent the last day searching and reading various sites and articles to try to find the answer to this question myself and I haven't found anything that helps. I'm not even sure if this is feasible. My problem is that I am trying to parse and extract a Json Response using lift-json. The response consists of 4 parts, where the first 3 parts are always the same for every response to every type of request I make. The last part varies depending on the type of request, but it is always going to be a list of some type. I was hoping to do something like this:
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]])
Where if I wanted to know what all the apples are, I would make a request for that and get back a response with a list of apples. When I try to extract this example:
myJson.extract[Fruits[Apple]]
I get this 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:...
I'm using lift-json 2.1 & scala 2.8. I do have a way to work around it, by specifically creating a case class for each type of response, but I thought what I was trying to do was cleaner. Just wanted to know if
a) is this even possible?
b) if so, what am I doing wrong?
EDIT...sample 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))))
I want doesntWork to be like works, Where:
case class AFruit(aisle: Int, bin: Int, hasWhat: Option[List[Apple]])
Thanks!
-newbie
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
尚不支持提取参数化案例类。一种解决方法(但不确定这是否适合您的情况)是使 Fruits 成为具体类型并将类型信息添加到 JSON 中。
打印:
Extracting parameterized case class is not yet supported. One workaround (not sure if this works for your case though) is to make Fruits a concrete type and add the type information into JSON.
That prints: