在Scala中,解析json并映射到对象的最简单方法是什么?
我正在寻找一种超级简单的方法来获取一个大的JSON片段,这是一个包含大量大对象的长列表,并对其进行解析,然后从每个对象中选择相同的几个值,然后映射到一个case类中 我已经非常努力地让lift json(2.5)为我工作,但是我很难清楚地处理检查是否存在密钥的问题,如果存在,则映射整个对象,如果不存在,则跳过它 我一点也不懂这个语法:在Scala中,解析json并映射到对象的最简单方法是什么?,scala,lift,lift-json,Scala,Lift,Lift Json,我正在寻找一种超级简单的方法来获取一个大的JSON片段,这是一个包含大量大对象的长列表,并对其进行解析,然后从每个对象中选择相同的几个值,然后映射到一个case类中 我已经非常努力地让lift json(2.5)为我工作,但是我很难清楚地处理检查是否存在密钥的问题,如果存在,则映射整个对象,如果不存在,则跳过它 我一点也不懂这个语法: case class Car(make: String, model: String) ... val parsed = parse(jsonFragment
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类车(品牌:String,型号:String)
...
val parsed=parse(jsonFragment)
val JArray(汽车)=已解析/“汽车”
val carList=新可变列表[汽车]
对于(car来说,奇怪的赋值是在val
声明中使用的模式匹配
当你看到
val JArray(cars) = parsed / "cars"
它从解析的json中提取“cars”
对象的子树,并将结果值与提取器模式jarray(cars)
也就是说,值应该是构造函数jarray(something)
的形式,something
绑定到cars
变量名
它的工作原理与您可能熟悉的case类基本相同,例如选项,例如
//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类有一个免费的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
——所以我写选项[t]
在案例类中。因为您只想提取某些字段,所以您的思路是正确的。此用于理解的修改版本将在您的汽车结构中循环,提取品牌和型号,并且仅在两个项目都存在时才生成案例类:
for{
car <- cars
model <- (car \ "model").extractOpt[String]
make <- (car \ "make").extractOpt[String]
} yield Car(make, model)
在这两种情况下,您都会得到一个Car
案例类的列表。我有点困惑-您是想为每个项目挑选一些值来用该子集填充案例类,还是想使用这些值对案例对象执行一些测试,然后用整个记录填充案例对象?@jcern我只是想挑选一些值并用subset.extractOpt填充case类对我不起作用…我得到“找不到参数格式的隐式值:net.liftweb.json.formats”我能做些什么来解决这个问题?啊,我没有添加“implicit val formats=net.liftweb.json.DefaultFormats”您能免费解释一下unapply是什么意思吗?这是否意味着,如果case类位于赋值运算符的左侧,所有case类都会反转apply函数的效果?这意味着case类会为您生成许多样板文件,其中一个是模式匹配使用的unapply方法。您可以这样做val语句中的模式匹配(如果不匹配,则会出现运行时错误)。因此您可以执行以下操作:案例类C(a:Int,b:Int,C:Int);val x=C(1,2,3);val C(a,b,)=x;断言(a==1)+1谢谢您的解释,这对我非常有帮助。(当然还有+1,也谢谢您的原始答案!)
for{
car <- cars
model <- (car \ "model").extractOpt[String]
make <- (car \ "make").extractOpt[String]
} yield Car(make, model, (car \ "color").extractOpt[String])