当前位置: 首页 > 知识库问答 >
问题:

使用Spark从json字符串列表中提取数组

华涵意
2023-03-14

我的数据框中有一列包含JSON列表,但类型是字符串。我需要在此列上运行分解,因此首先需要将其转换为列表。我找不到太多关于这个用例的参考。

示例数据:

列名称:"[{"name":"a","info":{"age":"1","等级":"b"},"其他": 7},{"随机":"x"},{...}]"

上面是数据的样子,字段是不固定的(索引0可能有JSON和一些字段,而索引1将有一些字段和一些其他字段)。列表中可以有更多嵌套的JSONs或一些额外的字段。我现在正在用这个-

<code>“分解(拆分(regexp_replace(regexp_replace(colName),(\\\},),“},”),“(\\[|\\\]),”,“,”,”,))为colName“”,</code>我只是用“}”替换“}”,然后删除“[]”,然后在“}”上调用拆分,但这种方法不起作用,因为存在嵌套的JSON。

如何从字符串中提取数组?

共有1个答案

桑睿识
2023-03-14

您可以尝试以下方式:

// Initial DataFrame

df.show(false)

+----------------------------------------------------------------------+
|columnName                                                            |
+----------------------------------------------------------------------+
|[{"name":"a","info":{"age":"1","grade":"b"},"other":7},{"random":"x"}]|
+----------------------------------------------------------------------+

df.printSchema()

root
 |-- columnName: string (nullable = true)
 
// toArray is a user defined function that parses an array of json objects which is present as a string
     
import org.json.JSONArray

val toArray = udf { (data: String) => {
    val jsonArray = new JSONArray(data)
    var arr: Array[String] = Array()
    val objects = (0 until jsonArray.length).map(x => jsonArray.getJSONObject(x))
    objects.foreach { elem =>
        arr :+= elem.toString
    }
    arr
}
}

// Using the udf and exploding the resultant array

val df1 = df.withColumn("columnName",explode(toArray(col("columnName"))))

df1.show(false)

+-----------------------------------------------------+
|columnName                                           |
+-----------------------------------------------------+
|{"other":7,"name":"a","info":{"grade":"b","age":"1"}}|
|{"random":"x"}                                       |
+-----------------------------------------------------+

df1.printSchema()

root
 |-- columnName: string (nullable = true)
 
// Parsing the json string by obtaining the schema dynamically

val schema = spark.read.json(df1.select("columnName").rdd.map(x => x(0).toString)).schema
val df2 = df1.withColumn("columnName",from_json(col("columnName"),schema))

df2.show(false)

+---------------+
|columnName     |
+---------------+
|[[1, b], a, 7,]|
|[,,, x]        |
+---------------+

df2.printSchema()

root
 |-- columnName: struct (nullable = true)
 |    |-- info: struct (nullable = true)
 |    |    |-- age: string (nullable = true)
 |    |    |-- grade: string (nullable = true)
 |    |-- name: string (nullable = true)
 |    |-- other: long (nullable = true)
 |    |-- random: string (nullable = true)
 
// Extracting all the fields from the json

df2.select(col("columnName.*")).show(false)

+------+----+-----+------+
|info  |name|other|random|
+------+----+-----+------+
|[1, b]|a   |7    |null  |
|null  |null|null |x     |
+------+----+-----+------+

编辑:

如果您可以使用get_json_object功能,则可以尝试这种方式

// Get the list of columns dynamically

val columns = spark.read.json(df1.select("columnName").rdd.map(x => x(0).toString)).columns

// define an empty array of Column type and get_json_object function to extract the columns

var extract_columns: Array[Column] = Array()
    columns.foreach { column =>
    extract_columns :+= get_json_object(col("columnName"), "$." + column).as(column)
}

df1.select(extract_columns: _*).show(false)

+-----------------------+----+-----+------+
|info                   |name|other|random|
+-----------------------+----+-----+------+
|{"grade":"b","age":"1"}|a   |7    |null  |
|null                   |null|null |x     |
+-----------------------+----+-----+------+

请注意,< code>info列不是struct类型。您可能必须遵循类似的方法来提取嵌套json的列

 类似资料:
  • 我正在从Spark读取一个dynamodb表,这个表在一个字段中有一个JSON字符串,在其他字段中有字符串。我能够读取JSON字段,但不能读取嵌套的JSON字段。这不是使用dataframes的查询Json列的副本。这个问题解释了如何从JSON字符串中提取列,但没有解释嵌套的JSON列。 users.show(1) 示例数据集 我需要从col1(JSON结构)和ID字段中提取几个字段。我能够理解如

  • 问题内容: 我有一个包含Json的字符串。看起来像这样: 我正在尝试保留“ img_url”。我已经安装了Json.NET,并且在这里发现了类似的问题。 例如这样的事情: 在我来说,我改变到,etc..no运气 现在这是我的代码: 在提取值之前,是否必须对字符串做一些事情?谢谢! 问题答案: 不是根对象的属性-它是对象的属性: 另外的选择:

  • 我在spark dataframe中有一个包含文本的列。 我想提取所有以特殊字符开头的单词,我正在使用从该文本列的每一行中提取。如果文本包含以开头的多个单词,则只返回第一个单词。 我正在寻找提取多个符合我在火花模式的单词。 样本输入:< code>@always_nidhi @YouTube不,我不明白,但我喜欢他们的音乐和舞蹈真棒这首mve的所有歌曲都很摇滚 示例输出:

  • 我正在使用ApacheJMeter发出HTTP请求。 响应格式如下: HTTP/1.1 100继续 HTTP/1.1 200 OK x-powering-by: Express access-Control-low-source:*access-Control-low-method: HEAD, POST, PUT, GET, OPTIONS, DELETE access-Control-low-

  • 我正在以JSON字符串的形式从数据库中获取数据: 如何从给定的JSON字符串中提取公司名称?

  • 问题内容: 我想从包含数字和字母的字符串中提取数字: 我想在这里获取号码或任何其他号码。 问题答案: