Scala - 如何获取 Json 字段的最大值?



我正在尝试从JSON字符串中获取MetricId字段的最大值。但是,我得到了以下字符串的java.lang.UnsupportedOperationException: empty.max

[{"MetricName":"name1","DateParsed":"2019-11-20 05:39:00","MetricId":"7855","isValid":"true"},
{"MetricName":"name2","DateParsed":"2019-05-22 17:45:00","MetricId":"1295","isValid":"false"}]

以下是我如何实现查找最大值的方法:

val metricIdRegex = """"MetricId"s*:s*(d+)""".r
def maxMetricId(jsonString: String): String = {
metricIdRegex.findAllIn(jsonString).map({
case metricIdRegex(id) => id.toInt
}).max.toString
}
val maxId: String = maxMetricId(metricsString)

我希望获得"7855"作为最大指标 ID

该方法可能有什么问题?我怀疑这可能是正则表达式的问题。

你也可以使用json4s,它非常流行,被许多其他scala库使用:

import org.json4s._
import org.json4s.jackson.JsonMethods._
val data = """[{"MetricName":"name1","DateParsed":"2019-11-20 05:39:00","MetricId":"7855","isValid":"true"},
{"MetricName":"name2","DateParsed":"2019-05-22 17:45:00","MetricId":"1295","isValid":"false"}]"""
// parse data into JValue
val parsed = parse(data)
// go through the parsed variable and extract MetricId into a string list, then cast every item to int
val maxMetricId = (parsed  "MetricId" \ classOf[JString]).map{_.toInt}.max

让我展示一个示例,如何使用 JSON 解析器有效地完成它,而无需在内存中保存整个 JSON 输入和解析的数据。

将依赖项添加到build.sbt

libraryDependencies ++= Seq(
"com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-core"   % "2.0.2" % Compile,
"com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-macros" % "2.0.2" % Provided // required only in compile-time
)

添加导入,定义一个数据结构来重复应该解析的 JSON 数组的一部分,为其派生编解码器,打开输入流并使用提供的处理函数对其进行扫描,这将把所有解析的指标减少到最大值:

import com.github.plokhotnyuk.jsoniter_scala.macros._
import com.github.plokhotnyuk.jsoniter_scala.core._
import java.io.ByteArrayInputStream
import java.io.InputStream
case class Metric(@stringified MetricId: Int)
implicit val codec: JsonValueCodec[Metric] = JsonCodecMaker.make(CodecMakerConfig)
val in: InputStream = new ByteArrayInputStream( // <- replace it by FileInputStream
"""[{"MetricName":"name1","DateParsed":"2019-11-20 05:39:00","MetricId":"7855","isValid":"true"},
{"MetricName":"name2","DateParsed":"2019-05-22 17:45:00","MetricId":"1295","isValid":"false"}]""".getBytes("UTF-8"))
try {
var max = -1
scanJsonArrayFromStream[Metric](in) { m: Metric =>
max = Math.max(max, m.MetricId)
true
}
println(max)
} finally in.close()

并且此代码应打印7855.

最新更新