将lift-json提取到具有上限的案例类中 [英] Extracting lift-json into a case class with an upper bound

查看:109
本文介绍了将lift-json提取到具有上限的案例类中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在过去的一天中,我一直在搜索和阅读各种站点和文章,以试图自己找到该问题的答案,但我没有找到任何有用的方法.我什至不确定这是否可行.我的问题是我正在尝试使用lift-json解析和提取Json Response.响应包括4个部分,其中前3个部分对于我提出的每种请求的每个响应始终是相同的.最后一部分根据请求的类型而有所不同,但始终是某些类型的列表.我希望做这样的事情:

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

我收到此错误:

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)如果是,我在做什么错了?

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 ...示例应用程序:

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

我希望工作不像作品,

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

谢谢! -新手

推荐答案

尚不支持提取参数化案例类.一种解决方法(不确定是否适合您的情况)是将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.

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"
  }]
}

这篇关于将lift-json提取到具有上限的案例类中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆