限制 jq 的输出深度

Ban*_*uin 5 json jq

我想使用jq. 为此,我想限制jq下降到文档的深度,只显示第一个n级别,例如 3 个级别。

假设我有以下 JSON 文档:

{
    "a": {
        "b": {
            "c": {
                "d": {
                    "e": "foo"
                }
            }
        }
    },
    "f": {
        "g": {
            "h": {
                "i": {
                    "j": "bar"
                }
            }
        }
    },
    "k": {
        "l": {
            "m": {
                "n": {
                    "o": "baz"
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我期待结果

{
    "a": {
        "b": {
            "c": {}
        }
    },
    "f": {
        "g": {
            "h": {}
        }
    },
    "k": {
        "l": {
            "m": {}
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我事先知道文档的结构,这是一项相当简单的任务,但通常我不知道。这就是为什么我希望能够jq只显示文档结构的前 n 层,这可能是字典和数组的任意嵌套。

一个更复杂的例子可能是:

[
    { "a": { "b": { "c": { "d": { "e": "foo"}}}}},
    { "f": [ { "g": "foo"}]},
    [ "h", "i", "j" ]
]
Run Code Online (Sandbox Code Playgroud)

我期望结果的地方

[
    { "a": { "b": {}},
    { "f": [{}]},
    [ "h", "i", "j" ]
]
Run Code Online (Sandbox Code Playgroud)

我可以jq这样做吗?

fra*_*san 8

将该del函数与.[]?数组/对象值迭代器结合以删除嵌套在第四级的任何键/值似乎给出了您正在寻找的结果:

$ jq 'del(.[]?[]?[]?[]?)' <<'EOT'
[
    { "a": { "b": { "c": { "d": { "e": "foo"}}}}},
    { "f": [ { "g": "foo"}]},
    [ "h", "i", "j" ]
]
EOT
[
  {
    "a": {
      "b": {}
    }
  },
  {
    "f": [
      {}
    ]
  },
  [
    "h",
    "i",
    "j"
  ]
]
Run Code Online (Sandbox Code Playgroud)

需要迭代器过滤器的.[]?版本,.[]以防止jq在尝试迭代不是数组或对象的项目时发出抱怨。

老实说,我.[][]在文档的任何地方都找不到上面显示的形式(基本上:)直接提及数组/对象迭代器过滤器。一个不太简洁但清楚记录的版本是:

$ jq 'del(.[]? | .[]? | .[]? | .[]?)' ...
Run Code Online (Sandbox Code Playgroud)


Kus*_*nda 5

使用path(..)您可以为给定文档生成所有可能的路径表达式。然后您可以使用例如选择太长的那些select(length > 3)。这些可以用 删除delpaths()

这样做的好处是允许我们编写一个简洁的表达式,可以轻松地使用单个整数进行参数化(可以将其传递给jqwith --argjson),但该path(..)表达式同时不必要地“重”(生成文档中的每个单个路径) )。

$ jq 'delpaths([path(..) | select(length > 3)])' file
{
  "a": {
    "b": {
      "c": {}
    }
  },
  "f": {
    "g": {
      "h": {}
    }
  },
  "k": {
    "l": {
      "m": {}
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

使用问题末尾的示例文档进行测试:

$ jq . file
[
  {
    "a": {
      "b": {
        "c": {
          "d": {
            "e": "foo"
          }
        }
      }
    }
  },
  {
    "f": [
      {
        "g": "foo"
      }
    ]
  },
  [
    "h",
    "i",
    "j"
  ]
]
Run Code Online (Sandbox Code Playgroud)
$ jq --argjson d 1 'delpaths([path(..) | select(length > $d)])' file
[
  {},
  {},
  []
]
Run Code Online (Sandbox Code Playgroud)
$ jq --argjson d 2 'delpaths([path(..) | select(length > $d)])' file
[
  {
    "a": {}
  },
  {
    "f": []
  },
  [
    "h",
    "i",
    "j"
  ]
]
Run Code Online (Sandbox Code Playgroud)
$ jq --argjson d 3 'delpaths([path(..) | select(length > $d)])' file
[
  {
    "a": {
      "b": {}
    }
  },
  {
    "f": [
      {}
    ]
  },
  [
    "h",
    "i",
    "j"
  ]
]
Run Code Online (Sandbox Code Playgroud)