簡體   English   中英

jq可以處理嵌套的JSON數據嗎?

[英]Can jq handle nested JSON data?

也許這對於'jq'來說太過分了,我需要跳入python json模塊,但是讓我們為大師們挑戰一下吧!

我有一些JSON數據(來自i3窗口管理器),看起來有點像這樣(簡化)。 我想深入挖掘任意數量的.nodes / .floating_nodes級別,並拉出將“ window”設置為非null的.nodes或.floating_nodes。

{
  "floating_nodes": [],
  "nodes": [
    {
      "floating_nodes": [],
      "nodes": [
        {
          "floating_nodes": [],
          "nodes": [
            {
              "floating_nodes": [],
              "nodes": [],
              "window": null,
              "name": "__i3_scratch",
            }
          ],
          "window": null,
          "name": "foobar",
        }
      ],
      "window": null,
      "name": "__i3",
    },
    {
      "floating_nodes": [],
      "nodes": [
        {
          "floating_nodes": [],
          "nodes": [],
          "window": null,
          "name": "topdock",
        },
        {
          "floating_nodes": [],
          "nodes": [
            {
              "floating_nodes": [],
              "nodes": [
                {
                  "floating_nodes": [],
                  "nodes": [],
                  "window": 8388613,
                  "name": "16:11 bhepple:.../~ — Konsole",
                  "rect": {
                    "height": 1061,
                    "width": 1920,
                    "y": 0,
                    "x": 0
                  },
              ],
              "window": null,
              "name": "1",
            }
          ],
          "window": null,
          "name": "content",
        },
        {
          "floating_nodes": [],
          "nodes": [
            {
              "floating_nodes": [],
              "nodes": [],
              "window": 14680070,
              "name": "i3bar for output VNC-0",
            }
          ],
          "window": null,
          "name": "bottomdock",
        }
      ],
      "window": null,
      "name": "VNC-0",
    }
  ],
  "window": null,
  "name": "root",
}

我的示例JSON被我的簡化打斷了,所以這是完整版本:

{"id":10883136,"type":"root","orientation":"horizontal","scratchpad_state":"none","percent":null,"urgent":false,"focused":false,"layout":"splith","workspace_layout":"default","last_split_layout":"splith","border":"pixel","current_border_width":-1,"rect":{"x":0,"y":0,"width":1920,"height":1080},"deco_rect":{"x":0,"y":0,"width":0,"height":0},"window_rect":{"x":0,"y":0,"width":0,"height":0},"geometry":{"x":0,"y":0,"width":0,"height":0},"name":"root","window":null,"nodes":[{"id":10883568,"type":"output","orientation":"none","scratchpad_state":"none","percent":0.5,"urgent":false,"focused":false,"layout":"output","workspace_layout":"default","last_split_layout":"splith","border":"pixel","current_border_width":-1,"rect":{"x":0,"y":0,"width":1920,"height":1080},"deco_rect":{"x":0,"y":0,"width":0,"height":0},"window_rect":{"x":0,"y":0,"width":0,"height":0},"geometry":{"x":0,"y":0,"width":0,"height":0},"name":"__i3","window":null,"nodes":[{"id":10884128,"type":"con","orientation":"horizontal","scratchpad_state":"none","percent":null,"urgent":false,"focused":false,"layout":"splith","workspace_layout":"default","last_split_layout":"splith","border":"pixel","current_border_width":-1,"rect":{"x":0,"y":0,"width":0,"height":0},"deco_rect":{"x":0,"y":0,"width":0,"height":0},"window_rect":{"x":0,"y":0,"width":0,"height":0},"geometry":{"x":0,"y":0,"width":0,"height":0},"name":"content","window":null,"nodes":[{"id":10884720,"type":"workspace","orientation":"none","scratchpad_state":"none","percent":null,"urgent":false,"focused":false,"layout":"splith","workspace_layout":"default","last_split_layout":"splith","border":"pixel","current_border_width":-1,"rect":{"x":0,"y":0,"width":0,"height":0},"deco_rect":{"x":0,"y":0,"width":0,"height":0},"window_rect":{"x":0,"y":0,"width":0,"height":0},"geometry":{"x":0,"y":0,"width":0,"height":0},"name":"__i3_scratch","num":-1,"window":null,"nodes":[],"floating_nodes":[],"focus":[],"fullscreen_mode":1,"sticky":false,"floating":"auto_off","swallows":[]}],"floating_nodes":[],"focus":[10884720],"fullscreen_mode":0,"sticky":false,"floating":"auto_off","swallows":[]}],"floating_nodes":[],"focus":[10884128],"fullscreen_mode":0,"sticky":false,"floating":"auto_off","swallows":[]},{"id":10886256,"type":"output","orientation":"none","scratchpad_state":"none","percent":0.5,"urgent":false,"focused":false,"layout":"output","workspace_layout":"default","last_split_layout":"splith","border":"pixel","current_border_width":-1,"rect":{"x":0,"y":0,"width":1920,"height":1080},"deco_rect":{"x":0,"y":0,"width":0,"height":0},"window_rect":{"x":0,"y":0,"width":0,"height":0},"geometry":{"x":0,"y":0,"width":0,"height":0},"name":"VNC-0","window":null,"nodes":[{"id":10886944,"type":"dockarea","orientation":"none","scratchpad_state":"none","percent":null,"urgent":false,"focused":false,"layout":"dockarea","workspace_layout":"default","last_split_layout":"splith","border":"pixel","current_border_width":-1,"rect":{"x":0,"y":0,"width":1920,"height":0},"deco_rect":{"x":0,"y":0,"width":0,"height":0},"window_rect":{"x":0,"y":0,"width":0,"height":0},"geometry":{"x":0,"y":0,"width":0,"height":0},"name":"topdock","window":null,"nodes":[],"floating_nodes":[],"focus":[],"fullscreen_mode":0,"sticky":false,"floating":"auto_off","swallows":[{"dock":2,"insert_where":2}]},{"id":10887648,"type":"con","orientation":"horizontal","scratchpad_state":"none","percent":null,"urgent":false,"focused":false,"layout":"splith","workspace_layout":"default","last_split_layout":"splith","border":"pixel","current_border_width":-1,"rect":{"x":0,"y":0,"width":1920,"height":1061},"deco_rect":{"x":0,"y":0,"width":0,"height":0},"window_rect":{"x":0,"y":0,"width":0,"height":0},"geometry":{"x":0,"y":0,"width":0,"height":0},"name":"content","window":null,"nodes":[{"id":10889056,"type":"workspace","orientation":"horizontal","scratchpad_state":"none","percent":null,"urgent":false,"focused":false,"layout":"splith","workspace_layout":"default","last_split_layout":"splith","border":"pixel","current_border_width":-1,"rect":{"x":0,"y":0,"width":1920,"height":1061},"deco_rect":{"x":0,"y":0,"width":0,"height":0},"window_rect":{"x":0,"y":0,"width":0,"height":0},"geometry":{"x":0,"y":0,"width":0,"height":0},"name":"1","num":1,"window":null,"nodes":[{"id":10895664,"type":"con","orientation":"none","scratchpad_state":"none","percent":1.0,"urgent":false,"focused":true,"layout":"splith","workspace_layout":"default","last_split_layout":"splith","border":"pixel","current_border_width":1,"rect":{"x":0,"y":0,"width":1920,"height":1061},"deco_rect":{"x":0,"y":0,"width":0,"height":0},"window_rect":{"x":1,"y":1,"width":1918,"height":1059},"geometry":{"x":0,"y":0,"width":958,"height":1059},"name":"16:11 bhepple:.../~ — Konsole","window":8388613,"window_properties":{"class":"konsole","instance":"konsole","title":"16:11 bhepple:.../~ — Konsole","transient_for":null},"nodes":[],"floating_nodes":[],"focus":[],"fullscreen_mode":0,"sticky":false,"floating":"auto_off","swallows":[]}],"floating_nodes":[],"focus":[10895664],"fullscreen_mode":1,"sticky":false,"floating":"auto_off","swallows":[]}],"floating_nodes":[],"focus":[10889056],"fullscreen_mode":0,"sticky":false,"floating":"auto_off","swallows":[]},{"id":10888352,"type":"dockarea","orientation":"none","scratchpad_state":"none","percent":null,"urgent":false,"focused":false,"layout":"dockarea","workspace_layout":"default","last_split_layout":"splith","border":"pixel","current_border_width":-1,"rect":{"x":0,"y":1061,"width":1920,"height":19},"deco_rect":{"x":0,"y":0,"width":0,"height":0},"window_rect":{"x":0,"y":0,"width":0,"height":0},"geometry":{"x":0,"y":0,"width":0,"height":0},"name":"bottomdock","window":null,"nodes":[{"id":10891392,"type":"con","orientation":"none","scratchpad_state":"none","percent":1.0,"urgent":false,"focused":false,"layout":"splith","workspace_layout":"default","last_split_layout":"splith","border":"pixel","current_border_width":1,"rect":{"x":0,"y":1061,"width":1920,"height":19},"deco_rect":{"x":0,"y":0,"width":0,"height":0},"window_rect":{"x":0,"y":0,"width":1920,"height":19},"geometry":{"x":0,"y":1061,"width":3840,"height":19},"name":"i3bar for output VNC-0","window":14680070,"window_properties":{"class":"i3bar","instance":"i3bar","title":"i3bar for output VNC-0","transient_for":null},"nodes":[],"floating_nodes":[],"focus":[],"fullscreen_mode":0,"sticky":false,"floating":"auto_off","swallows":[]}],"floating_nodes":[],"focus":[10891392],"fullscreen_mode":0,"sticky":false,"floating":"auto_off","swallows":[{"dock":3,"insert_where":2}]}],"floating_nodes":[],"focus":[10887648,10886944,10888352],"fullscreen_mode":0,"sticky":false,"floating":"auto_off","swallows":[]}],"floating_nodes":[],"focus":[10886256,10883568],"fullscreen_mode":0,"sticky":false,"floating":"auto_off","swallows":[]}

當然,jq可以做到這一點!

首先,我們使用遞歸運算符.. ,對所有內容進行遞歸迭代。 然后,獲得所有的.nodes.floating_nodes ,並使用? 忽略嘗試從數字,字符串或對象中獲取屬性而產生的錯誤。 然后,使用[]獲得這些數組中的所有元素。 再次,忽略在上一步中的錯誤留下一些null S,所以我們試圖使用忽略錯誤[]null ,以及符合S ? 最后,我們將所有內容通過管道傳遞給select(.window != null) ,並將每個結果包裝在數組中以便於處理。

jq '[.. | .floating_nodes?, .nodes? | .[]? | select(.window != null)]'

如果window屬性只能出現在nodefloating_node對象上,則可以通過僅搜索具有window屬性的所有對象來簡化操作。

.. | objects | select(.window != null)

解決聖地亞哥的解決方案,並嘗試回填jq-1.3中可能缺少的內容,我可以這樣做:

jq 'recurse(.[]) | .floating_nodes, .nodes | .[] | select(.window != null) | select(.focused == true) | .name'

...它還給出了許多錯誤消息,例如:

jq: error: Cannot iterate over number
jq: error: Cannot iterate over null
jq: error: Cannot iterate over null
jq: error: Cannot index number with string

以下已通過jq 1.3、1.4和1.5進行了測試:

recurse(if type == "object" or type == "array" then .[] else empty end)
| select(type == "object")
| ( select(.nodes|type == "array") | .nodes[]),
  ( select(.floating_nodes|type == "array") | .floating_nodes[])
| select( .window != null ) 

使用給定輸入的“完整版本”,jq 1.3產生以下輸出:

{
  "swallows": [],
  "floating": "auto_off",
  "sticky": false,
  "fullscreen_mode": 0,
  "focus": [],
  "floating_nodes": [],
  "nodes": [],
  "window_properties": {
    "transient_for": null,
    "title": "16:11 bhepple:.../~ — Konsole",
    "instance": "konsole",
    "class": "konsole"
  },
  "window": 8388613,
  "name": "16:11 bhepple:.../~ — Konsole",
  "layout": "splith",
  "focused": true,
  "urgent": false,
  "percent": 1,
  "scratchpad_state": "none",
  "orientation": "none",
  "type": "con",
  "id": 10895664,
  "workspace_layout": "default",
  "last_split_layout": "splith",
  "border": "pixel",
  "current_border_width": 1,
  "rect": {
    "height": 1061,
    "width": 1920,
    "y": 0,
    "x": 0
  },
  "deco_rect": {
    "height": 0,
    "width": 0,
    "y": 0,
    "x": 0
  },
  "window_rect": {
    "height": 1059,
    "width": 1918,
    "y": 1,
    "x": 1
  },
  "geometry": {
    "height": 1059,
    "width": 958,
    "y": 0,
    "x": 0
  }
}
{
  "swallows": [],
  "floating": "auto_off",
  "sticky": false,
  "fullscreen_mode": 0,
  "focus": [],
  "floating_nodes": [],
  "nodes": [],
  "window_properties": {
    "transient_for": null,
    "title": "i3bar for output VNC-0",
    "instance": "i3bar",
    "class": "i3bar"
  },
  "window": 14680070,
  "name": "i3bar for output VNC-0",
  "layout": "splith",
  "focused": false,
  "urgent": false,
  "percent": 1,
  "scratchpad_state": "none",
  "orientation": "none",
  "type": "con",
  "id": 10891392,
  "workspace_layout": "default",
  "last_split_layout": "splith",
  "border": "pixel",
  "current_border_width": 1,
  "rect": {
    "height": 19,
    "width": 1920,
    "y": 1061,
    "x": 0
  },
  "deco_rect": {
    "height": 0,
    "width": 0,
    "y": 0,
    "x": 0
  },
  "window_rect": {
    "height": 19,
    "width": 1920,
    "y": 0,
    "x": 0
  },
  "geometry": {
    "height": 19,
    "width": 3840,
    "y": 1061,
    "x": 0
  }
}

這是一個使用tostream掃描來自給定輸入的[path,value]數組流的解決方案。 然后,它使用select來選擇僅以“ window”結尾且其對應值不為null的路徑。 最后,它使用foreachgetpath生成包含對象的流。

foreach (   tostream
          | select(length == 2 and .[0][-1] == "window" and .[1] != null)
        ) as $p (
    .
  ; .
  ; getpath($p[0][:-1])
)

編輯:我現在意識到形式為foreach E as $X (.; .; R)的過濾器foreach E as $X (.; .; R)幾乎總是可以重寫為E as $X | R E as $X | R所以上面真的是

  ( tostream | select(length == 2 and .[0][-1] == "window" and .[1] != null) ) as $p
|  getpath($p[0][:-1])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM