如何基于JQ路径列表过滤JSON生成仅含指定内容的新JSON?
根据指定JQ路径列表提取JSON内容的最佳方案
如果你需要从原始JSON中提取指定JQ路径对应的内容,同时自动忽略不存在的路径并保留正确的嵌套结构,我推荐使用**reduce结合path和setpath**的方案——它比walk函数更灵活,能直接处理标准的JQ路径表达式(包括数组通配符[])。
问题回顾
假设我们有这样的原始JSON:
{ "id":"038020", "title":"Teenage Mutant Ninja Turtles: Out of the Shadows", "turtles":[ {"name":"Leonardo", "mask":"blue"}, {"name":"Michelangelo", "mask":"orange"}, {"name":"Donatello", "mask":"purple"}, {"name":"Raphael", "mask":"red"} ], "summary":"The Turtles continue to live in the shadows and no one knows they were the ones who took down Shredder", "cast":"Megan Fox, Will Arnett, Tyler Perry", "director":"Dave Green" }
和路径列表:[".turtles[].name", ".cast", ".does.not.exist"],我们需要生成只包含有效路径对应内容的新JSON,同时自动忽略不存在的.does.not.exist路径。
核心解决方案
使用以下JQ脚本可以完美实现需求:
# 保存原始输入到变量,方便后续复用 . as $input | # 定义要提取的路径列表 [".turtles[].name", ".cast", ".does.not.exist"] as $path_list | # 初始化空结果对象 {} | # 遍历每个路径表达式 reduce $path_list[] as $expr (.; # 辅助函数:处理单个路径,返回路径数组与对应值的配对列表 def process_path: path($expr) as $paths; $expr as $val; [$paths[], $val] | transpose; # 处理当前路径,获取所有路径-值配对 $input | process_path as $entries | # 将每个配对设置到结果对象中 reduce $entries[] as $entry (.; setpath($entry[0]; $entry[1]) ) )
执行结果
运行上述脚本后,会得到预期的输出:
{ "turtles": [ {"name": "Leonardo"}, {"name": "Michelangelo"}, {"name": "Donatello"}, {"name": "Raphael"} ], "cast": "Megan Fox, Will Arnett, Tyler Perry" }
方案优势
- 支持标准JQ路径:可以直接使用像
.turtles[].name(数组通配符)、.turtles[2].name(指定索引)这类常见路径表达式 - 自动忽略无效路径:如果路径不存在(比如
.does.not.exist),path($expr)会返回空数组,不会在结果中生成任何无效内容 - 保留原始结构:自动构建嵌套的数组和对象结构,只保留指定路径的字段
- 兼容jq 1.5+:不需要额外扩展,在主流jq版本中都能运行
命令行实用示例
如果你的原始JSON在input.json文件中,路径列表每行一个保存在paths.txt中,可以用以下命令批量处理:
jq -n --argjson paths "$(jq -R . paths.txt | jq -s .)" ' . as $input | ($paths | map(ltrimstr("."))) as $clean_paths | # 移除路径开头的点(如果存在) {} | reduce $clean_paths[] as $expr (.; def process_path: path($expr) as $paths; $expr as $val; [$paths[], $val] | transpose; $input | process_path as $entries | reduce $entries[] as $entry (.; setpath($entry[0]; $entry[1]) ) ) ' input.json
内容的提问来源于stack exchange,提问作者caulitomaz
相关产品推荐
相关产品推荐

