使用jq按指定key过滤内容无输出,疑fromstream存在问题求助
解决jq中fromstream无法重建包含指定key的JSON结构问题
问题重现
使用过滤器 fromstream(tostream | select(.[0]|index("foo"))) 处理修改后的JSON时无输出,预期保留包含foo的完整分支结构。
修改后的输入JSON:
{ "A": { "A1": { "foo": { "_": "_" } }, "A2": { "_": "_" } }, "B": { "B1": {} } }
预期输出:
{ "A": { "A1": { "foo": { "_": "_" } } } }
问题原因
原过滤器仅保留路径中直接包含foo的流条目,但tostream生成的流需要完整的节点生命周期条目(包括上层节点的创建/结束标记)才能被fromstream正确重建。原过滤逻辑丢弃了构建A、A1这些上层节点所需的流条目,导致fromstream无法生成任何有效结构。
从单独执行tostream | select(.[0]|index("foo"))的输出也能看出:仅保留了foo节点内部的条目,缺少A、A1节点的相关流标记。
解决方案
方案1:修复流过滤逻辑
保留所有属于foo节点上层路径的流条目,确保fromstream能重建完整结构:
( paths(has("foo")) ) as $fooPaths | fromstream(tostream | select(.[0] as $p | $fooPaths | any(.[:$p|length] == $p)))
方案2:使用reduce和paths构建结构
更直观的方式,找到所有包含foo的节点路径,将对应结构复制到空对象中:
reduce paths(. | has("foo")) as $path ({}; setpath($path; getpath($path)))
方案3:简洁的流过滤写法
通过判断路径是否包含foo,或路径是包含foo的路径的前缀,来保留必要条目:
fromstream(tostream | select(.[0] as $p | $p | any(. == "foo") or ($p | (paths | select(contains(["foo"])) | .[:$p|length]) | any(. == $p))))
验证
以上任一方案处理输入JSON后,均可得到预期的包含foo分支的输出结构。
内容的提问来源于stack exchange,提问作者Bin He
相关产品推荐
相关产品推荐

