You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Apache Spark Scala将DataFrame转换为嵌套多级JSON?

Spark DataFrame 转嵌套JSON:内置函数还是自定义UDF/UDAF?

原始DataFrame结构

+-------------------+-------+------+--------------------+
|         col_1     |  col_2| col_3|               col_4|
+-------------------+-------+------+--------------------+
|a                  |b      |c     |                  14|
|a                  |e      |f     |                  32|
|k                  |z      |x     |                  15|
+-------------------+-------+------+--------------------+

目标JSON格式

{"a": {"b": {"c": 14}, "e": {"f": 32}}, "k": {"z": {"x": 15}}}

解决方案:使用Spark内置函数即可,无需自定义UDF/UDAF

可以通过Spark提供的create_map、map_concat(或map_merge+aggregate)、collect_list等内置函数组合实现,无需编写自定义UDF/UDAF。

1. Spark 3.0+ 版本实现(推荐)

以PySpark为例:

from pyspark.sql import functions as F

# 初始化示例DataFrame
df = spark.createDataFrame(
    [("a", "b", "c", 14), ("a", "e", "f", 32), ("k", "z", "x", 15)],
    ["col_1", "col_2", "col_3", "col_4"]
)

# 构建嵌套映射并转为JSON
result_df = df.groupBy("col_1").agg(
    # 同col_1分组内,合并每个col_2对应的嵌套map
    F.map_concat(F.collect_list(F.create_map(F.col("col_2"), F.create_map(F.col("col_3"), F.col("col_4"))))).alias("nested_map")
).agg(
    # 合并所有col_1对应的map,并转为JSON字符串
    F.to_json(F.map_concat(F.collect_list(F.create_map(F.col("col_1"), F.col("nested_map"))))).alias("result_json")
)

# 查看输出
result_df.show(truncate=False)

Scala版本实现:

import org.apache.spark.sql.functions._

val df = spark.createDataFrame(Seq(
  ("a", "b", "c", 14), ("a", "e", "f", 32), ("k", "z", "x", 15)
)).toDF("col_1", "col_2", "col_3", "col_4")

val resultDf = df.groupBy("col_1")
  .agg(map_concat(collect_list(create_map(col("col_2"), create_map(col("col_3"), col("col_4"))))).alias("nested_map"))
  .agg(to_json(map_concat(collect_list(create_map(col("col_1"), col("nested_map"))))).alias("result_json"))

resultDf.show(false)

2. Spark 2.x 兼容版本

如果使用Spark 2.x(无map_concat函数),可以用aggregate+map_merge替代:

from pyspark.sql import functions as F

df = spark.createDataFrame(
    [("a", "b", "c", 14), ("a", "e", "f", 32), ("k", "z", "x", 15)],
    ["col_1", "col_2", "col_3", "col_4"]
)

result_df = df.groupBy("col_1").agg(
    F.collect_list(F.create_map(F.col("col_2"), F.create_map(F.col("col_3"), F.col("col_4")))).alias("map_list")
).agg(
    F.to_json(
        # 聚合所有col_1对应的map,合并为一个大map
        F.aggregate(
            F.collect_list(F.create_map(F.col("col_1"), 
                # 聚合组内的多个map,合并为单个map
                F.aggregate(F.col("map_list"), F.lit({}), lambda acc, m: F.map_merge(acc, m))
            )),
            F.lit({}),
            lambda acc, m: F.map_merge(acc, m)
        )
    ).alias("result_json")
)

result_df.show(truncate=False)

核心逻辑说明

  • create_map:用于构建键值对映射,从最内层的col_3 -> col_4开始,逐层向外嵌套col_2 -> 内层map、col_1 -> 中层map。
  • map_concat/map_merge:用于合并同组内的多个map,避免键值冲突(本例中同col_1下的col_2无重复,合并后自然形成嵌套结构)。
  • collect_list:用于收集分组内的所有映射结果,为合并做准备。
  • to_json:将最终的顶层map转换为符合要求的JSON字符串。

内容的提问来源于stack exchange,提问作者Ficush

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 10:34:59