我正在寻找一个通用的解决方案,从json字符串列中将所有json字段提取为列。
df = spark.read.load(path)
df.show()
“path”中文件的文件格式是parquet
样本数据
|id | json_data
| 1 | {"name":"abc", "depts":["dep01", "dep02"]}
| 2 | {"name":"xyz", "depts":["dep03"],"sal":100}
| 3 | {"name":"pqr", "depts":["dep02"], "address":{"city":"SF","state":"CA"}}
预期产量
|id | name | depts | sal | address_city | address_state
| 1 | "abc" | ["dep01", "dep02"] | null| null | null
| 2 | "xyz" | ["dep03"] | 100 | null | null
| 3 | "pqr" | ["dep02"] | null| "SF" | "CA"
我知道我可以通过创建一个定义了模式的structtype并使用'from_json'方法来提取列。
但这种方法需要手动定义模式。
val myStruct = StructType(
Seq(
StructField("name", StringType),
StructField("depts", ArrayType(StringType)),
StructField("sal", IntegerType)
))
var newDf = df.withColumn("depts", from_json(col("depts"), myStruct))
有没有更好的方法可以在不手动定义模式的情况下展平json列?在提供的示例中,我可以看到可用的json字段。但实际上,我无法遍历所有行来查找所有字段。
因此,我正在寻找一种解决方案,将所有字段拆分为列,而不指定列的名称或类型。
3条答案
按热度按时间2nbm6dog1#
假设
json_data
属于类型map
(您始终可以将其转换为map
如果不是),你可以用getItem
:更具动态性的列提取方法:
pn9klfpd2#
基于@gaurang shah的回答,我实现了一个处理嵌套json结构的解决方案,并修复了使用单调递增的id(非顺序)的问题
在这种方法中,“populatecolumnname”函数递归地检查structtype列并填充列名。
“renamecolumns”函数通过将“.”替换为“\”来重命名列,以标识嵌套的json字段。
“addindex”函数在解析json列后向dataframe添加索引以加入dataframe。
sd2nnvve3#
如果它是一个
CSV
只有一列作为JSON
数据。您可以使用以下解决方案。这就是最终Dataframe的样子。
如果它是一个
JSON
文件。为了我。inferSchema
很好用。json文件
代码