使用Scala/Spark读取JSON文件如何将顶层键转为行ID并展开嵌套字段
实现思路
你读取JSON后得到单行多列结构,是因为该JSON的顶层为键值对结构,所有id是顶层键,对应的值为嵌套结构体。你只需要先把多列id逆透视转成行,再展开嵌套字段即可实现目标格式,以下是可直接复用的实现代码:
PySpark 实现
固定字段版本(适合数据结构固定的场景)
from pyspark.sql import functions as F # 1. 读取JSON文件 df = spark.read.json("file.json") # 2. 逆透视将多列id转为行 unpivot_df = df.selectExpr("stack(3, 'id1', id1, 'id2', id2, 'id3', id3) as (id, data)") # 3. 展开嵌套字段并重命名 result = unpivot_df.select( "id", F.col("data.a").alias("col1"), F.col("data.b").alias("col2"), F.col("data.c").alias("col3"), F.col("data.d").alias("col4"), F.col("data.e").alias("col5"), F.col("data.f").alias("col6"), F.col("data.g").alias("col7"), F.col("data.h").alias("col8"), F.col("data.i").alias("col9"), F.col("data.j").alias("col10") ) # 输出结果 result.show()
动态通用版本(适合id数量、嵌套字段不固定的场景,无需手动写全所有列)
from pyspark.sql import functions as F df = spark.read.json("file.json") # 动态生成逆透视参数,适配任意数量的id列 id_cols = df.columns stack_param = f"stack({len(id_cols)}, {','.join([f'\'{c}\', {c}' for c in id_cols])}) as (id, data)" unpivot_df = df.selectExpr(stack_param) # 动态获取嵌套字段,自动按顺序重命名为col1~coln data_fields = unpivot_df.select("data.*").columns select_expr = ["id"] + [F.col(f"data.{field}").alias(f"col{i+1}") for i, field in enumerate(data_fields)] result = unpivot_df.select(*select_expr) result.show()
Scala 实现
import org.apache.spark.sql.functions._ val df = spark.read.json("file.json") val idCols = df.columns // 生成逆透视表达式 val stackExpr = s"stack(${idCols.length}, ${idCols.map(c => s"'$c', $c").mkString(",")}) as (id, data)" val unpivotDf = df.selectExpr(stackExpr) // 自动展开嵌套字段并重命名 val dataFields = unpivotDf.select("data.*").columns val selectExpr = col("id") +: dataFields.zipWithIndex.map{case (field, idx) => col(s"data.$field").alias(s"col${idx+1}")} val result = unpivotDf.select(selectExpr:_*) result.show()
内容的提问来源于stack exchange,提问作者david garcia
相关产品推荐
相关产品推荐

