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

如何将Spark DataFrame数组类型列转为字符串且保留元素结构

Spark DataFrame数组列转字符串时保留字段名/结构

问题背景

需要将Spark DataFrame中的array类型列转换为字符串类型,同时保留该列数据的元素字段名与结构。

DataFrame Schema

root
 |-- accountId: string (nullable = true)
 |-- documents: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- accountId: string (nullable = true)
 |    |    |-- agreementId: string (nullable = true)
 |    |    |-- createdBy: string (nullable = true)
 |    |    |-- createdDate: string (nullable = true)
 |    |    |-- id: string (nullable = true)
 |    |    |-- obligations: array (nullable = true)
 |    |    |    |-- element: string (containsNull = true)
 |    |    |-- resourceVersion: long (nullable = true)
 |    |    |-- updatedBy: string (nullable = true)
 |    |    |-- updatedDate: string (nullable = true)

示例数据

{
    "accountId":"1",
    "documents":{
        "list":[{
            "element":{
                "accountId":"1",
                "agreementId":"1.2",
                "createdDate":"2022-10-06T19:33:42.539646Z",
                "externalId":"16",
                "id":"123",
                "name":"test1.docx",
                "obligations":{},
                "resourceVersion":1,
                "updatedDate":"2022-10-06T19:33:42.680233Z"
            }
        }]
    }
}
{
    "accountId":"2",
    "documents":{
        "list":[{
            "element":{
                "accountId":"2",
                "agreementId":"2.2",
                "createdDate":"2022-10-06T19:33:42.539646Z",
                "externalId":"18",
                "id":"123",
                "name":"test2.docx",
                "obligations":{},
                "resourceVersion":1,
                "updatedDate":"2022-10-06T19:33:42.680233Z"
            }
        }]
    }
}

当前代码及问题

使用直接强制转换的方式:

df_string = df.select([col(c).cast("string") for c in df.columns])

问题:转换后documents列的结构体字段名丢失,变成无键值的元组形式:

{
    "accountId":"1",
    "documents":[{"1","1.2","2022-10-06T19:33:42.539646Z","16","123","test1.docx","",1,"2022-10-06T19:33:42.680233Z"}]
}
{
    "accountId":"2",
    "documents":[{"2","2.2","2022-10-06T19:33:42.539646Z","18","123","test2.docx","","1","2022-10-06T19:33:42.680233Z"}]
}

期望结果

转换后documents列保留完整字段名与结构:

{
    "accountId":"1",
    "documents":[{"accountId":"1","agreementId":"1.2","createdDate":"2022-10-06T19:33:42.539646Z","externalId":"16","id":"123","name":"test1.docx","obligations":"","resourceVersion":"1","updatedDate":"2022-10-06T19:33:42.680233Z"}]
}
{
    "accountId":"2",
    "documents":[{"accountId":"2","agreementId":"2.2","createdDate":"2022-10-06T19:33:42.539646Z","externalId":"18","id":"123","name":"test2.docx","obligations":"","resourceVersion":"1","updatedDate":"2022-10-06T19:33:42.680233Z"}]
}

解决方案

直接cast("string")会丢失复杂类型的结构信息,应使用to_json函数将数组列序列化为JSON格式的字符串,完整保留字段名与层级结构。

方式1:仅转换指定数组列

from pyspark.sql.functions import to_json, col

# 将documents列转为JSON字符串,其他列保持原类型(如需转字符串可额外cast)
df_string = df.withColumn("documents", to_json(col("documents")))

方式2:自动识别所有数组列转换

如果DataFrame中有多个数组列,可遍历列类型自动处理:

from pyspark.sql.functions import to_json, col

converted_columns = []
for col_name in df.columns:
    col_type = df.schema[col_name].dataType.typeName()
    if col_type == "array":
        # 数组列用to_json转字符串
        converted_columns.append(to_json(col(col_name)).alias(col_name))
    else:
        # 非数组列直接cast为字符串
        converted_columns.append(col(col_name).cast("string").alias(col_name))

df_string = df.select(converted_columns)

说明:to_json函数会将array、struct等复杂类型转换为标准JSON格式的字符串,完全保留字段名与数据结构,符合期望结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 20:55:23