如何使用jq的--streaming模式展开超大JSON文件中的文档?
用jq流式处理超大JSON数组展开需求
给定超大JSON文件,结构如下:
[ { "a": 4, "b": [1,2,3] }, { "a": 6, "b": [7,8,9] } ]
需要转换为:
{ "a": 4, "b": 1 }, { "a": 4, "b": 2 }, { "a": 4, "b": 3 }, { "a": 6, "b": 7 }, { "a": 6, "b": 8 }, { "a": 6, "b": 9 }
小文件可以用.[] | {a: .a, b: .b[]}处理,但超大文件需要启用--stream模式避免内存溢出,以下是实现方法。
流式处理的jq过滤器
流式模式下,jq会将JSON拆解为[路径, 值]的条目序列,我们需要通过维护状态来关联每个对象的a值和其b数组中的元素。
过滤器代码(保存为filter.jq)
reduce inputs as $i ( { current_a: null, index: null }; if $i[0][-1] == "a" then { current_a: $i[1], index: $i[0][0] } elif $i[0][-2] == "b" and $i[0][0] == .index then ( {a: .current_a, b: $i[1] } ) , . else . ) | select(type == "object")
执行命令
jq --stream -n -f filter.jq your_large_file.json
或者直接在命令行使用单行过滤器:
jq --stream -n 'reduce inputs as $i ( { current_a: null, index: null }; if $i[0][-1] == "a" then { current_a: $i[1], index: $i[0][0] } elif $i[0][-2] == "b" and $i[0][0] == .index then ( {a: .current_a, b: $i[1] } ) , . else . end ) | select(type == "object")' your_large_file.json
工作原理
- 状态维护:使用
reduce跟踪两个状态变量:current_a(当前对象的a值)和index(当前处理的数组元素索引)。 - 捕获a值:当遇到路径末尾为
"a"的条目时,更新状态,记录该对象的索引和a值。 - 生成结果:当遇到路径倒数第二位为
"b"且索引匹配当前状态的条目时,结合current_a生成目标对象并输出。 - 过滤输出:最后过滤掉状态对象,只保留生成的目标JSON对象。
关键参数说明
--stream:启用流式处理,逐块读取JSON,不加载整个文件到内存。-n:禁用默认读取标准输入为JSON的行为,改用inputs获取流式条目。
内容的提问来源于stack exchange,提问作者Ztyx
相关产品推荐
相关产品推荐

