我想使用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
这样做吗?
将该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)
使用path(..)
您可以为给定文档生成所有可能的路径表达式。然后您可以使用例如选择太长的那些select(length > 3)
。这些可以用 删除delpaths()
。
这样做的好处是允许我们编写一个简洁的表达式,可以轻松地使用单个整数进行参数化(可以将其传递给jq
with --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)