【问题标题】:Spark: Remove null values after from_json or just get value from a jsonSpark:在 from_json 之后删除空值或仅从 json 获取值
【发布时间】:2021-05-31 07:15:36
【问题描述】:

我有一个带有 JSON 数据列的 spark 数据框:

df = spark.createDataFrame(
     [
         (1, '{"a": "hello"}'),
         (2, '{"b": ["foo", "bar"]}'),
         (3, '{"c": {"cc": "baz"}}'),
         (4, '{"d": [{"dd": "foo"}, {"dd": "bar"}]}'),
     ],
     schema=['id', 'jsonData'],
)

df.show()
+---+--------------------+
| id|            jsonData|
+---+--------------------+
|  1|      {"a": "hello"}|
|  2|{"b": ["foo", "ba...|
|  3|{"c": {"cc": "baz"}}|
|  4|{"d": [{"dd": "fo...|
+---+--------------------+

键是模式标识符。也就是说,两个键不能有不同的架构

我需要解析此列中的 json 并从每个 dict 中获取值。

我运行下一个命令:

from pyspark.sql.functions import from_json
json_schema = spark.read.json(df.select("jsonData").rdd.map(lambda x: x[0])).schema
df = df.withColumn("jsonParsedData", from_json("jsonData", json_schema))

df.show()
+---+--------------------+--------------------+
| id|            jsonData|      jsonParsedData|
+---+--------------------+--------------------+
|  1|      {"a": "hello"}|          [hello,,,]|
|  2|{"b": ["foo", "ba...|    [, [foo, bar],,]|
|  3|{"c": {"cc": "baz"}}|         [,, [baz],]|
|  4|{"d": [{"dd": "fo...|[,,, [[foo], [bar]]]|
+---+--------------------+--------------------+

我有一个 jsonParsedData 列,其中包含缺少键的 null 值。

问题:如何从 jsonData 列解析 JSON 并获取缺少 null 值的列。

我认为jsonParsedData 列应该有string 类型。

预期结果

+---+--------------------+--------------------+
| id|            jsonData|      jsonParsedData|
+---+--------------------+--------------------+
|  1|      {"a": "hello"}|               hello|
|  2|{"b": ["foo", "ba...|          [foo, bar]|
|  3|{"c": {"cc": "baz"}}|       {"cc": "baz"}|
|  4|{"d": [{"dd": "fo...|[{"dd": "foo"}, {...|
+---+--------------------+--------------------+

【问题讨论】:

    标签: python json apache-spark pyspark apache-spark-sql


    【解决方案1】:

    尝试使用regexp_extract从json中提取值:

    import pyspark.sql.functions as F
    
    df2 = df.withColumn('jsonParsedData', F.regexp_extract('jsonData', '\\{"[^"]+": (.*)\\}', 1))
    
    df2.show(truncate=False)
    +---+-------------------------------------+------------------------------+
    |id |jsonData                             |jsonParsedData                |
    +---+-------------------------------------+------------------------------+
    |1  |{"a": "hello"}                       |"hello"                       |
    |2  |{"b": ["foo", "bar"]}                |["foo", "bar"]                |
    |3  |{"c": {"cc": "baz"}}                 |{"cc": "baz"}                 |
    |4  |{"d": [{"dd": "foo"}, {"dd": "bar"}]}|[{"dd": "foo"}, {"dd": "bar"}]|
    +---+-------------------------------------+------------------------------+
    

    另一种可能更好的方法是将from_jsonmap<string, string> 架构一起使用:

    import pyspark.sql.functions as F
    
    df2 = df.withColumn('jsonParsedData', F.map_values(F.from_json('jsonData', 'map<string,string>'))[0])
    
    df2.show(truncate=False)
    +---+-------------------------------------+---------------------------+
    |id |jsonData                             |jsonParsedData             |
    +---+-------------------------------------+---------------------------+
    |1  |{"a": "hello"}                       |hello                      |
    |2  |{"b": ["foo", "bar"]}                |["foo","bar"]              |
    |3  |{"c": {"cc": "baz"}}                 |{"cc":"baz"}               |
    |4  |{"d": [{"dd": "foo"}, {"dd": "bar"}]}|[{"dd":"foo"},{"dd":"bar"}]|
    +---+-------------------------------------+---------------------------+
    

    【讨论】:

      猜你喜欢
      • 2019-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-21
      • 2013-09-06
      • 1970-01-01
      相关资源
      最近更新 更多