You need to enable JavaScript to run this app. Spark使用from_json解析JSON后如何移除null值或直接提取字段值
优惠活动
大模型
产品
解决方案
定价
更多

Spark使用from_json解析JSON后如何移除null值或直接提取字段值

问题根因

之前的解析逻辑之所以出问题,核心是schema推导方式不对:

  • 用spark.read.json扫描全量JSON文本推导schema时,会把所有行出现过的顶层键(也就是本例里的a、b、c、d四个完全不重叠的键)合并成一个包含4个字段的StructType结构
  • from_json解析时严格按照这个合并后的Struct结构逐行匹配,凡是Struct里存在但当前行JSON没有的键,都会自动填充null占位,最终才会输出类似[hello,,,]这种带空位置的结构
  • 你实际需要的是每行JSON里那个唯一顶层键对应的原始值,不管这个值是字符串、数组还是嵌套对象,把它转成字符串就行,根本不需要套用把所有键凑到一起的Struct结构。
实现方案

因为你已经明确了:不同行的JSON顶层键完全不重叠,每行只有1个顶层键,完全没必要提前推导全局合并schema,用灵活的Map结构逐行解析就可以做到无null占位,而且最终输出直接是string类型。

代码实现

from pyspark.sql.functions import from_json, map_values, element_at, col
from pyspark.sql.types import MapType, StringType

# 定义Map格式的解析schema:键为字符串,值统一按字符串存储任意嵌套的JSON内容
map_schema = MapType(StringType(), StringType())

df_result = (
    df
    # 把原来的jsonData列逐行解析为Map结构,每行的Map仅包含自身JSON里的那一个键值对
    .withColumn("json_map", from_json(col("jsonData"), map_schema))
    # 取出Map里唯一的value,作为最终的jsonParsedData列
    .withColumn("jsonParsedData", element_at(map_values(col("json_map")), 1))
    # 删掉临时用的中间列
    .drop("json_map")
)

实际输出

执行df_result.show(truncate=False)就能得到你预期的效果:

+---+----------------------------------------+------------------------------------+
|id |jsonData                                |jsonParsedData                      |
+---+----------------------------------------+------------------------------------+
|1  |{"a": "hello"}                          |"hello"                             |
|2  |{"b": ["foo", "bar"]}                   |["foo","bar"]                       |
|3  |{"c": {"cc": "baz"}}                    |{"cc":"baz"}                        |
|4  |{"d": [{"dd": "foo"}, {"dd": "bar"}]}   |[{"dd":"foo"},{"dd":"bar"}]         |
+---+----------------------------------------+------------------------------------+

方案说明

  • 不会出现跨行键合并带来的null占位:因为全程没有把所有行的键强行拼到一个Struct结构里,每行的Map只保留自己JSON本身带的键,别的行的键根本不会被拉进来
  • 最终输出列本身就是string类型,不需要额外做类型转换
  • 兼容任意格式的JSON值:不管值是纯字符串、数组、嵌套对象还是对象数组,都能正确提取

兼容低版本Spark的替代方案:如果用的Spark版本不支持Map类型灵活解析嵌套JSON,可以直接用正则抠内容——写正则表达式^\{".*?":(.*)\}$匹配jsonData列,提取第一个捕获组的内容就是目标值,这种方式完全不依赖schema推导,同样不会产生null占位。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.01 20:36:03