Spark - 如何将 JSON 转义的字符串字段解析为 DataFrames 中的 JSON 对象?

Posted

技术标签:

【中文标题】Spark - 如何将 JSON 转义的字符串字段解析为 DataFrames 中的 JSON 对象?【英文标题】:Spark - How to parse a JSON-escaped String field as a JSON Object in DataFrames? 【发布时间】:2017-06-23 19:10:44 【问题描述】:

我有一组文件作为输入,每行格式化为一个 JSON 对象。然而,问题在于这些 JSON 对象上的一个字段是 JSON 转义字符串。示例

"clientAttributes":"backfillId":null,"clientPrimaryKey":"abc","escapedJsonPayload":"\"name\":\"Akash\",\"surname\":\"Patel\",\"items\":[\"itemId\":\"abc\",\"itemName\":\"xyz\""

当我通过读取 json 文件创建数据框时,它正在创建如下数据框

val df = spark.sqlContext.read.json("file:///home/akaspate/sample.json")
df: org.apache.spark.sql.DataFrame = [clientAttributes: struct<backfillId: string, clientPrimaryKey: string>, escapedJsonPayload: string]

我们可以看到“escapedJsonPayload”是字符串,我需要它是结构。

注意:我在 *** 中遇到了类似的问题并关注了它 (How to let Spark parse a JSON-escaped String field as a JSON Object to infer the proper structure in DataFrames?) 但它给了我“[_corrupt_record: string]”

我已经尝试了以下步骤

    val df = spark.sqlContext.read.json("file:///home/akaspate/sample.json") (Work file)

    val escapedJsons: RDD[String] = sc.parallelize(Seq("""df"""))

    val unescapedJsons: RDD[String] = escapedJsons.map(_.replace("\"", "").replace("\"", "").replace("\\\"", "\""))

    val dfJsons: DataFrame = spark.sqlContext.read.json(unescapedJsons) (This results in [_corrupt_record: string])

任何帮助将不胜感激

【问题讨论】:

【参考方案1】:

首先,您提供的 JSON 格式错误(语法上)。修正后的 JSON 如下:

"clientAttributes":"backfillId":null,"clientPrimaryKey":"abc","escapedJsonPayload":\"name\":\"Akash\",\"surname\":\"Patel\",\"items\":[\"itemId\":\"abc\",\"itemName\":\"xyz\"]

接下来,要从上述 JSON 中正确解析 JSON,您必须使用以下代码:

val rdd = spark.read.textFile("file:///home/akaspate/sample.json").toJSON.map(value => value.replace("\\", "").replace("\"value\":\"", "").replace("\"", "")).rdd

val df = spark.read.json(rdd)

上面的代码会给你以下输出:

df.show(false)

+----------------+-------------------------------------+
|clientAttributes|escapedJsonPayload                   |
+----------------+-------------------------------------+
|[null,abc]      |[WrappedArray([abc,xyz]),Akash,Patel]|
+----------------+-------------------------------------+

使用以下架构:

df.printSchema

root
 |-- clientAttributes: struct (nullable = true)
 |    |-- backfillId: string (nullable = true)
 |    |-- clientPrimaryKey: string (nullable = true)
 |-- escapedJsonPayload: struct (nullable = true)
 |    |-- items: array (nullable = true)
 |    |    |-- element: struct (containsNull = true)
 |    |    |    |-- itemId: string (nullable = true)
 |    |    |    |-- itemName: string (nullable = true)
 |    |-- name: string (nullable = true)
 |    |-- surname: string (nullable = true)

我希望这会有所帮助!

【讨论】:

感谢 himanshuIIITian@ 详细解答。关于“首先您提供的 JSON 格式错误(语法上)”,我们无法控制此输入文件,并且我们从上游服务获取此格式。所以它看起来像这样“escapedJsonPayload”:“\”name\”:\“Akash\””。你能告诉我们如何在 Spark 中处理这个问题吗? 简单...只需在 JSON 值上应用 replace("\\", "")。就像我在回答中提到的那样。 @AkashPatel 请接受答案或提供反馈。 接受了答案。感谢您的帮助

以上是关于Spark - 如何将 JSON 转义的字符串字段解析为 DataFrames 中的 JSON 对象?的主要内容,如果未能解决你的问题,请参考以下文章

Spark SQL 读取已转义双引号的 JSON 文件

如何在 Spark SQL 中使用连字符转义列名

如何将字符串中带有双引号的json文件加载到spark scala中的数据框中

如何在Spark SQL中查询StringType的1个字段具有json值的数据框

使用 Spark 从 DynamoDB JSON 字符串中提取嵌套的 Json 字段?

数据库json列在laravel刀片中返回转义字符串