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



我正在寻找一种超级简单的方法来获取一个大的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])

我希望jValuesmilesname——否则提取将失败。

我不期望jValue必须有firstNamelastName——所以我在case类中写Option[T]

相关内容

  • 没有找到相关文章