PySpark处理带动态列名的嵌套JSONL:转换为指定数据格式
Spark提取JSONL嵌套字段解决方案
问题背景
原始JSONL数据如下:
{"id": 1, "data": {"key:1": {"string_value": "value_1"}, "key:2": {"string_value": "value_2"}, "user_id": {"string_value": "value_4"}}} {"id": 2, "data": {"key:3": {"string_value": "value_3"}, "user_id": {"string_value": "value_5"}}}
使用df.select("id", "data.*")处理后,得到的列都是struct类型(包含string_value子字段),而非直接的字符串值,不符合预期:
+---+---------+---------+---------+---------+ |id |key:1 |key:2 |key:3 |user_id | +---+---------+---------+---------+---------+ |1 |{value_1}|{value_2}|null |{value_4}| |2 |null |null |{value_3}|{value_5}| +---+---------+---------+---------+---------+ root |-- id: long (nullable = true) |-- key:1: struct (nullable = true) | |-- string_value: string (nullable = true) |-- key:2: struct (nullable = true) | |-- string_value: string (nullable = true) |-- key:3: struct (nullable = true) | |-- string_value: string (nullable = true) |-- user_id: struct (nullable = true) | |-- string_value: string (nullable = true)
解决方案
需要提取每个struct字段里的string_value,将其转换为直接的字符串列。可以通过遍历展开后的字段,逐个提取嵌套值:
完整代码示例
from pyspark.sql import SparkSession from pyspark.sql.functions import col # 初始化SparkSession spark = SparkSession.builder.appName("ExtractNestedField").getOrCreate() # 读取JSONL数据(替换为你的数据路径) df = spark.read.json("path/to/your/data.jsonl", multiLine=False) # 先展开data字段,获取所有需要处理的列 expanded_df = df.select("id", "data.*") # 获取除id外的所有列名 non_id_columns = [col_name for col_name in expanded_df.columns if col_name != "id"] # 对每个非id列,提取string_value并重命名为原列名 processed_columns = [col(col_name).getField("string_value").alias(col_name) for col_name in non_id_columns] # 组合id列和处理后的列 final_df = expanded_df.select("id", *processed_columns) # 展示结果和schema final_df.show(200, False) final_df.printSchema()
预期结果
处理后的数据会变成:
+---+-------+-------+-------+-------+ |id |key:1 |key:2 |key:3 |user_id| +---+-------+-------+-------+-------+ |1 |value_1|value_2|null |value_4| |2 |null |null |value_3|value_5| +---+-------+-------+-------+-------+
对应的schema:
root |-- id: long (nullable = true) |-- key:1: string (nullable = true) |-- key:2: string (nullable = true) |-- key:3: string (nullable = true) |-- user_id: string (nullable = true)
说明
- 使用
getField("string_value")从struct类型字段中提取嵌套的字符串值 - 通过列表推导式批量处理所有非id字段,避免逐个手动编写提取逻辑,适合字段较多的场景
- 如果你的字段名包含特殊字符(比如
:),Spark会自动处理,无需额外转义
内容的提问来源于stack exchange,提问作者zigi
相关产品推荐
相关产品推荐

