我正在寻找一种超级简单的方法来获取一个大的JSON片段,这是一个长列表,其中有一堆大对象,并解析它,然后从每个对象中挑选出相同的几个值,然后映射到一个case类。
我已经很努力地让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
我还是不太清楚。
帮助是非常感谢 !!!!!
既然您只希望提取某些字段,那么您就走上了正确的道路。这个修改版本的for-comprehension
将循环遍历您的汽车结构,提取make和model,只有在两者都存在时才生成case类:
for{
car <- cars
model <- (car "model").extractOpt[String]
make <- (car "make").extractOpt[String]
} yield Car(make, model)
您将以相同的方式添加其他必需字段。如果你还想使用可选参数,比如color
-那么你可以在yield部分调用它for推导式不会打开它们:
for{
car <- cars
model <- (car "model").extractOpt[String]
make <- (car "make").extractOpt[String]
} yield Car(make, model, (car "color").extractOpt[String])
在这两种情况下,您将获得Car
案例类的List
。
这个奇怪的赋值是在val
声明中使用的模式匹配。
看到
val JArray(cars) = parsed / "cars"
它从解析的json中提取"cars"
对象的子树,并将结果值与提取器模式 JArrays(cars)
匹配。
也就是说,该值应该是构造函数JArrays(something)
的形式,并且something
绑定到cars
变量名。
它的工作原理与您可能熟悉的case类(如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
对象中对应的内部case类,在这里
找到 case类有一个免费的unapply
方法,它允许您执行模式匹配,如上面的答案所述。
我想这应该适合你:
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
——所以我在case类中写Option[T]
。