如何在Spark SQL中从JSON列提取动态数量的键值对
解决JSON列提取指定模式键值对的问题
问题原因
get_json_object的JSONPath语法不支持通配符匹配键名,所以$.test-*-value这种写法会返回NULL,无法提取动态键名的内容。
可行解决方法
以下方案适用于Hive或Spark SQL,根据你的环境选择:
方法1:拆分键值对后过滤重组(通用兼容)
SELECT concat('{', concat_ws(',', collect_list(concat('"', key, '":"', value, '"'))), '}') AS extracted_out FROM ( -- 替换成你的表名和JSON列名,这里用示例字符串 SELECT explode(from_json('{"random_field": "ABC", "test-0-value":"1", "test-1-value":"2"}', 'map<string, string>')) AS (key, value) ) t -- 用正则匹配test-N-value格式的键名,\d匹配数字,可根据需求调整 WHERE key RLIKE '^test-\\d+-value$';
执行后会输出符合预期的JSON字符串。如果处理表中数据,把from_json里的字符串替换为你的JSON列名即可。
方法2:Spark SQL简洁写法(推荐)
如果使用Spark SQL,可利用map_filter和to_json直接处理,避免字符串拼接的潜在问题:
SELECT to_json( map_filter( from_json('{"random_field": "ABC", "test-0-value":"1", "test-1-value":"2"}', 'map<string, string>'), (k, v) => k rlike '^test-\\d+-value$' ) ) AS extracted_out;
这个方法会自动处理JSON格式的转义,结果更规范可靠。
注意事项
- 正则表达式
^test-\\d+-value$匹配的是test-后接数字、再跟-value的键名,如果你的键名中N是多位数字或其他格式,可调整正则(比如^test-[0-9]+-value$匹配多位数字)。 - 如果JSON中的值包含双引号,方法1的字符串拼接会出错,此时优先使用方法2。
内容的提问来源于stack exchange,提问作者Sam Comber
相关产品推荐
相关产品推荐

