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

Pyspark DataFrame解析含None值的JSON数组列异常怎么解决?

问题根因

你遇到的解析失败并非schema定义错误,核心有两个原因:

  • 你存储的cast列JSON为Python风格格式:使用单引号包裹键值、空值用None表示,不符合标准JSON要求(标准JSON用双引号、空值为null),PySpark默认按标准JSON规则解析会报错
  • from_json解析后返回的是ArrayType(StructType)结构,直接调用getField("name")无法正确提取数组内每个struct的name字段
可行解决方案

有两种可直接落地的处理方式,均兼容全量4.5万条数据的批量处理:

方案1:预处理JSON格式后解析(兼容性最优,推荐)

先将cast列的非标准JSON转为标准格式,再执行解析,代码如下:

from pyspark.sql.functions import regexp_replace, from_json, col, transform, concat_ws

# 1. 转换为标准JSON格式:替换单引号为双引号,替换None为null
credits_upd = credits_upd.withColumn(
    "cast_std",
    regexp_replace(regexp_replace(col("cast"), "'", '"'), "None", "null")
)

# 原schema定义无需修改,已设置nullable=True支持空值
cast_schema=ArrayType(StructType([
  StructField('cast_id',IntegerType(),nullable=True),
  StructField('character',StringType(),nullable=True),
  StructField('credit_id',StringType(),nullable=True),
  StructField('gender',IntegerType(),nullable=True),
  StructField('id',IntegerType(),nullable=True),
  StructField('name',StringType(),nullable=True),
  StructField('order',IntegerType(),nullable=True),
  StructField('profile_path',StringType(),nullable=True)
]))

# 2. 解析JSON并提取演员名,按需选择返回格式
# 格式1:保留数组格式的演员名列表
credits_upd = credits_upd.withColumn(
    "movies_cast",
    transform(from_json(col("cast_std"), cast_schema), lambda item: item.name)
)

# 格式2:转为逗号分隔的字符串
# credits_upd = credits_upd.withColumn(
#     "movies_cast",
#     concat_ws(",", transform(from_json(col("cast_std"), cast_schema), lambda item: item.name))
# )

# 验证结果
credits_upd.select("id", "movies_cast").show(truncate=False)

方案2:配置from_json参数适配非标准JSON

无需预处理列,直接通过解析参数适配非标准格式,代码如下:

from pyspark.sql.functions import from_json, col, transform

cast_schema=ArrayType(StructType([
  StructField('cast_id',IntegerType(),nullable=True),
  StructField('character',StringType(),nullable=True),
  StructField('credit_id',StringType(),nullable=True),
  StructField('gender',IntegerType(),nullable=True),
  StructField('id',IntegerType(),nullable=True),
  StructField('name',StringType(),nullable=True),
  StructField('order',IntegerType(),nullable=True),
  StructField('profile_path',StringType(),nullable=True)
]))

credits_upd = credits_upd.withColumn(
    "movies_cast",
    transform(
        # 配置允许单引号、非标准空值的解析参数
        from_json(col("cast"), cast_schema, options={"allowSingleQuotes": "true", "allowNonNumericNumbers": "true"}),
        lambda item: item.name
    )
)

credits_upd.select("id", "movies_cast").show(truncate=False)

两种方案都可以正确解析id=8844的记录,提取到Robin Williams的名字。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 03:57:01