如何在 Apache Spark 中爆炸 get_json_object

Man*_*ani 5 arrays json explode apache-spark apache-spark-sql

我的数据框列之一中有以下字符串:

row1:[{"key":"foo"},{"key":"bar"},{"key":"baz"}]
row2:[{"key":"foo"},{"key":"bar"}]
row3:null
etc
Run Code Online (Sandbox Code Playgroud)

我发现 Spark 具有“get_json_object”功能。因此,如果我想使用 xpath 提取数据,我将使用:

 get_json_object($"json", s"$[0].key")
Run Code Online (Sandbox Code Playgroud)

会返回:

"foo"
"foo"
null
Run Code Online (Sandbox Code Playgroud)

但我需要相当于 Spark 的“爆炸”功能。

我发现我可以在 xpath 上使用“*”符号。

 get_json_object($"json", s"$[*].key")
Run Code Online (Sandbox Code Playgroud)

哪个不按预期执行,它将创建一个字符串,如:

[foo,bar,baz]
[foo,baz]
Run Code Online (Sandbox Code Playgroud)

我在另一个 stackoverflow 线程中找到了解决方案,

val jsonElements = (0 until 3).map(i => get_json_object($"json", s"$$[$i].key"))


val jsonElements = .map(i => get_json_object($"json", s"$$[$i].key"))
df.select($"id",explode(array(jsonElements: _*).alias("foo")))
Run Code Online (Sandbox Code Playgroud)

这部分解决了我的问题,因为这个解决方案假定我知道我的阵列的最大深度。Spark 的函数“from_json”需要模式,我有巨大的复杂 JSON 类型需要“无限”的时间来创建模式。

免责声明

我不会使用任何正则表达式/子字符串/等来解析 JSON。使用解析器的整个建议就是这样。

Mun*_*nna -2

只要坚持 Scala 基础知识就可以简单地解决它。尝试带有选项的案例类来解决问题。

您可以使用任何标准 json 解析器。我用的是liftweb。

import net.liftweb.json.{DefaultFormats, parseOpt}

case class jsonElement(key: String, value: Optional[String])
//assuming the value key always exists and value may or may not exist, 
//so making that as optional / ignore the fields if you don't really care at all

val jsonKeys = inputRdd.map(eachRow => 
  implicit val formats = DefaultFormats // hate this but deal with scala

  val parsedObject = parseOpt(eachRow).flatMap(_.extractOpt[List[jsonElement]])

  parsedObject match{
    case Some(parsedItem) => parsedItem.map(json => json.key)
    case None => List()
})
Run Code Online (Sandbox Code Playgroud)

这给出了列表(键)的 Rdd。如果要删除空列表,请使用filter(list => !list.isEmpty)。你从那里就知道了。