如何获取包含已知对象的 json 的子树

How to get subtree of json containing known object

我想用 jqi3-msg -t get_tree 中提取包含焦点 window 的子树。我知道重点 window 可以通过

找到

i3-msg -t get_tree | jq ".. | (.nodes? // empty)[] | select(.focused == true)"

一个简单的例子是:

{
  "node": [
    {
      "node": {
        "foo": "bar"
      }
    },
    {
      "node": {
        "foo": "foo"
      }
    }
  ]
}

如果搜索包含 .foo == "bar"node,则输出应该 return

{
  "node": [
    {
      "node": {
        "foo": "bar"
      }
    }
  ]
}

但我似乎找不到合适的方法来提取从根到该节点的子树。

.node |= map(select(.node.foo == "bar"))

这个概念被称为Update assignment

原始问题有两个不同的子问题,一个与 .. 的使用有关,但未参考发布的 JSON 示例,另一个基于特定类型的 JSON 输入。此响应使用基于使用 paths 的策略:

reduce pv as [$p,$v] (null; setpath($p; $v))

这可能会或可能不会按需要处理数组,部分取决于需要什么。如果通常不需要数组中的 null 值,则按如下方式添加对 walk/1 的调用是合适的:

walk(if type == "array" then map(select(. != null)) else . end)

或者,如果必须保留原件中存在的 null 值,则可以使用下面 附录 中详述的策略。

(1) 使用..

表征的问题
def pv:
 paths as $p
 | getpath($p)
 | . as $v
 | (.nodes? // empty)[] | select(.focused == true)
 | [$p,$v];

reduce pv as [$p,$v] (null; setpath($p; $v))

如上所述,要消除所有数组中的所有空值,您可以添加对 walk/1 的调用。否则,如果 setpathnull 值插入数组以保留原始结构的各个方面,请参阅下面的 附录

(2) 对于样本JSON,满足以下条件:

def pv:
 paths as $p
 | getpath($p)
 | . as $v
 | (.node? // empty) | select(.foo == "bar")
 | [$p,$v];

reduce pv as [$p,$v] (null; setpath($p; $v))

对于给定的样本,这会产生:

{"node":[{"node":{"foo":"bar"}}]}

对于类似的输入,如果要从数组中删除 null 值,只需像以前一样附加对 walk/1 的调用;另请参阅下面的附录

附录

如果不需要 setpath 可能插入数组以保留原始结构的 null 值,最简单的方法是更改​​原始 [=66] 中的 null 值=] 到某个独特的值(例如“:null:”),执行选择,trim null 值,然后将独特的值转换回 null

例子

例如,考虑 foo/bar 示例的这个变体:

{
  "node": [
    {
      "node": {
        "foo": "foo0"
      }
    },
    {
      "node": {
        "foo": "bar",
        "trouble": [
          null,
          1,
          null
        ]
      }
    },
    {
      "node": {
        "foo": "foo1"
      }
    },
    {
      "node": {
        "foo": "bar",
        "trouble": [
          1,
          2,
          3
        ]
      }
    }
  ],
  "nodes": [
    {
      "node": {
        "foo": "foo0"
      }
    },
    {
      "node": {
        "foo": "bar",
        "trouble": [
          null,
          1,
          null
        ]
      }
    }
  ]
}

使用“:null:”作为区别值,可以使用先前针对此案例显示的 "main" 程序的以下变体:

walk(if type == "array" then map(if . == null then ":null:" else . end) else . end)
| reduce pv as [$p,$v] (null; setpath($p; $v))
| walk(if type == "array"
       then map(select(. != null) | if . == ":null:" then null else . end)
       else . end)