使用原生Spark SQL解析含嵌套数组的JSON字符串数组
解决Spark SQL解析嵌套JSON数组并拆分行的问题
针对你遇到的问题,不需要自定义UDF或Serdes,用Spark SQL原生的from_json+explode就能完美解决,而且能避免正则拆分带来的嵌套结构误分割问题。
核心思路
- 首先用
from_json将存储JSON字符串的列解析成Spark的数组结构体类型,这样explode就能直接处理(因为explode要求输入是数组或map类型); - 用
explode将外层数组拆分成单行记录; - 提取外层字段,并用
to_json将inner_list转回字符串格式(满足你保留原嵌套结构字符串的需求)。
完整SQL示例
假设你的表名为wt_test,存储JSON数组的列名为outer_list,可以用下面的SQL直接得到目标结果:
SELECT outer_obj.outer_id, outer_obj.outer_field_1, to_json(outer_obj.inner_list) AS inner_list FROM wt_test LATERAL VIEW explode( from_json( outer_list, 'ARRAY<STRUCT<outer_id:INT, outer_field_1:STRING, inner_list:ARRAY<STRUCT<inner_id:INT>>>>' ) ) exploded_table AS outer_obj;
逐步骤解释
定义JSON Schema:
在from_json的第二个参数里,我们明确指定了JSON的结构:- 最外层是
ARRAY类型,每个元素是一个STRUCT; - 每个外层结构体包含
outer_id(整数)、outer_field_1(字符串)、inner_list(内层数组,元素是包含inner_id的结构体)。
你可以根据实际数据的类型调整这里的定义(比如如果outer_field_1是其他类型,修改对应的类型声明即可)。
- 最外层是
解析并拆分数组:
from_json把字符串格式的JSON数组转换成Spark可识别的数组结构体,之后explode就可以把数组的每个元素拆分成单独的行。保留inner_list为字符串:
用to_json把解析后的inner_list结构体数组重新转回JSON字符串,完美保留原嵌套结构的字符串形式。
为什么你之前的方法失败?
- 第一种方法:
get_json_object(outer_list, "$[*]")返回的仍然是字符串类型,而explode要求输入是数组或map类型,所以报错; - 第二种方法:用
split按逗号拆分,会把inner_list内部的逗号也当成分隔符,导致拆分出错误的片段,无法得到完整的外层JSON对象。
注意事项
- 确保你的JSON字符串格式是标准的:比如字符串类型的字段(比如
blah)要加双引号,否则from_json会解析失败; - 如果JSON里存在可选字段(可能为null),Spark的Schema默认支持nullable,不需要额外配置;如果需要强制非空,可以在Schema里用
NOT NULL声明(比如outer_id:INT NOT NULL)。
内容的提问来源于stack exchange,提问作者Lumo Woong
相关产品推荐
相关产品推荐

