2

我正在寻找一种超级简单的方法来获取一个大的 JSON 片段,这是一个包含一堆大对象的长列表,然后解析它,然后从每个对象中挑选出相同的几个值,然后映射到一个案例中班级。

我已经非常努力地让 lift-json (2.5) 为我工作,但是我在检查是否存在键时遇到了麻烦,如果存在,则映射整个对象,但如果不存在,则跳过它.

我绝对不理解 Lift-JSON 的这种语法:

case class Car(make: String, model: String)

...

val parsed = parse(jsonFragment)
val JArray(cars) = parsed / "cars"

val carList = new MutableList[Car]
for (car <- cars) {
    val JString(model) = car / "model"
    val JString(make) = car / "make"

    // i want to check if they both exist here, and if so 
    // then add to carList
    carList += car
}

到底是什么构造使它看起来像在赋值运算符的左侧创建案例类?我说的是“JString”部分。此外,它应该如何应对缺少钥匙的情况?

有人可以向我解释一下这样做的正确方法是什么吗?如果我有我正在寻找的嵌套值,我只想跳过整个对象并继续尝试映射下一个对象。

有没有比 Lift-JSON 更直接的方法?

使用extractOpt 会有帮助吗?

我看了很多: https ://github.com/lift/framework/tree/master/core/json

对我来说仍然不是特别清楚。

非常感谢帮助!!!!

4

3 回答 3

3

由于您只想提取某些字段,因此您走在正确的轨道上。这个修改后的版本for-comprehension将遍历您的汽车结构,提取品牌和型号,并且仅在这两个项目都存在时才产生您的案例类:

for{ 
  car <- cars
  model <- (car \ "model").extractOpt[String]
  make <- (car \ "make").extractOpt[String]
} yield Car(make, model)

您将以相同的方式添加其他必填字段。如果您还想使用可选参数,比方说color- 那么您可以在 yield 部分调用它,并且 for comprehension 不会将它们拆箱:

for{ 
  car <- cars
  model <- (car \ "model").extractOpt[String]
  make <- (car \ "make").extractOpt[String]
} yield Car(make, model, (car \ "color").extractOpt[String])

在这两种情况下,您都会得到一个List案例Car类。

于 2013-06-17T18:38:21.673 回答
2

看起来怪异的赋值是在声明中使用的模式匹配。val

当你看到

val JArray(cars) = parsed / "cars"

它从解析的 json 中提取"cars"对象的子树,并将结果值与提取器模式 JArrays(cars)匹配。
也就是期望值是构造函数的形式,JArrays(something)并且与变量名something绑定。cars

它的工作原理与您可能熟悉的案例类几乎相同Options,例如

//define a value with a class that can pattern match
val option = Some(1)
//do the matching on val assignment
val Some(number) = option
//use the extracted binding as a variable
println(number)

以下作业是完全相同的东西

//pattern match on a JSon String whose inner value is assigned to "model"
val JString(model) = car / "model"
//pattern match on a JSon String whose inner value is assigned to "make"
val JString(make) = car / "make"

参考

JSON 类型(例如)在此处JValue, JString, JDouble定义为net.liftweb.json对象内的别名。

别名又指向对象中相应的内部案例类net.liftweb.json.JsonAST,可在此处找到

案例类有一个unapply免费的方法,它可以让你按照上面的答案进行模式匹配。

于 2013-06-17T08:26:21.840 回答
2

我认为这应该适合你:

case class UserInfo(
        name: String,
        firstName: Option[String],
        lastName: Option[String],
        smiles: Boolean
        )

val jValue: JValue
val extractedUserInfoClass: Option[UserInfo] = jValue.extractOpt[UserInfo]

val jsonArray: JArray
val listOfUserInfos: List[Option[UserInfo]] = jsonArray.arr.map(_.extractOpt[UserInfo])

我希望jValuesmiles-name否则提取将失败。

我不希望jValue一定有firstNamelastName——所以我Option[T]在案例课上写。

于 2013-06-17T08:41:19.587 回答