scala upickle/ujson中JSON null的特殊处理



我是Scala的新手,想学习解决常见问题的惯用方法,比如Python的Python。我的问题是关于使用upickle读取JSON数据,其中JSON值在存在时包含字符串,在不存在时包含null。我想使用自定义值来替换null。一个简单的例子:

import upickle.default._
val jsonString = """[{"always": "foo", "sometimes": "bar"}, {"always": "baz", "sometimes": null}]"""
val jsonData = ujson.read(jsonString)
for (m <- jsonData.arr) {
println(m("always").str.length)  // this will work
println(m("sometimes").str.length)  // this will fail, Exception in thread "main" ujson.Value$InvalidData: Expected ujson.Str (data: null)
}

问题是字段"sometimes":当为null时,我们不能应用.str(或任何其他映射到null以外的静态类型的函数(。我正在寻找类似m("sometimes").str("DEFAULT").length的东西,其中"DEFAULT"是null的替换。

创意1使用模式匹配,以下作品:

val sometimes = m("sometimes") match {
case s: ujson.Str => s.str
case _ => "DEFAULT"
}
println(sometimes.length)

考虑到Scala简洁的语法,这看起来有点复杂,并且在为许多值执行时会重复。

想法2相关问题的答案提到创建具有默认值的案例类。对于我的问题,当根据上下文需要不同的替换值时,案例类的创建对我来说似乎是不灵活的。

想法3回答另一个问题(不是upickle特有的(,使用Try().getOrElse()进行讨论,即:

import scala.util.Try
// ...
println(Try(m("sometimes").str).getOrElse("DEFAULT").length)

然而,讨论中提到,为常规程序路径抛出异常是昂贵的。

解决这个问题的惯用而又简洁的方法是什么?

使用scala的Option实现这一点的惯用方法或scala方法。

幸运的是,upickle Values提供了它们。请参阅此源代码中的strOpt方法。

代码中的问题是m("总是"(.str和m("有时"(.str.中的str方法使用此代码,您过早地假设所有值都是字符串。这就是strOpt方法的用武之地。如果其值是字符串,则输出字符串;如果不是,则输出None类型。如果值为None,我们可以使用getOrElse方法来决定抛出什么。

以下将是处理此问题的最佳方式。

val jsonString = """[{"always": "foo", "sometimes": "bar"}, {"always": "baz", "sometimes": null}]"""
for (m <- jsonData.arr) {
println(m("always").strOpt.getOrElse("").length)  
println(m("sometimes").strOpt.getOrElse("").length) 
} 

输出:

3
3
3
0

在这里,如果我们得到字符串以外的任何值(null、float、int(,代码将把它输出为空字符串。其长度将计算为0。

基本上,这与您的";理想1";方法,但这是scala方法。代替";DEFAULT";,我抛出一个空字符串,因为您不希望null值的长度为7(字符串的长度"DEFAULT"(。

最新更新