在Scala中,解析json并映射到对象的最简单方法是什么?

在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

我正在寻找一种超级简单的方法来获取一个大的JSON片段,这是一个包含大量大对象的长列表,并对其进行解析,然后从每个对象中选择相同的几个值,然后映射到一个case类中

我已经非常努力地让lift json(2.5)为我工作,但是我很难清楚地处理检查是否存在密钥的问题,如果存在,则映射整个对象,如果不存在,则跳过它

我一点也不懂这个语法:

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