我正在寻找一个超级简单的方法来获取一个大的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
}
究竟是什么构造使它看起来像是在赋值运算符左边创建的case类?我在谈论“JString”部分。 它还应该如何应对缺少钥匙的情况?
有人可以向我解释一下这样做的正确方法是什么? 如果我有我正在寻找的嵌套值,我只想跳过整个对象并继续尝试映射下一个。
有没有比Lift-JSON更直接的东西?
会使用 extractOpt 帮助吗?
我看了很多: https://github.com/lift/framework/tree/master/core/json
对我来说仍然不是特别清楚。
帮助非常赞赏!!!!!
答案 0 :(得分: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
个案例类别。
答案 1 :(得分: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
对象here中的别名。
别名依次指向net.liftweb.json.JsonAST
对象中相应的内部案例类,找到here
案例类具有免费的unapply
方法,可让您按照上述答案中的说明进行模式匹配。
答案 2 :(得分: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])
我希望jValue
拥有smiles
和name
- 否则提取会失败。
我不希望jValue
必须有firstName
和lastName
- 所以我在案例类中写Option[T]
。