使用 JQ 删除具有某些键值对的父元素
Remove parent elements with certain key-value pairs using JQ
我需要根据某些键值从 json 文件中删除元素。这是我要处理的文件。
{
"element1": "Test Element 1",
"element2": {
"tags": "internal",
"data": {
"data1": "Test Data 1",
"data2": "Test Data 2"
}
},
"element3": {
"function1": {
"tags": [
"new",
"internal"
]
},
"data3": "Test Data 3",
"data4": "Test Data 4"
},
"element4": {
"function2": {
"tags": "new"
},
"data5": "Test Data 5"
}
}
我想删除所有具有值为“内部”的“标签”的元素。所以结果应该是这样的:
{
"element1": "Test Element 1",
"element4": {
"function2": {
"tags": "new"
},
"data5": "Test Data 5"
}
}
我尝试了各种方法,但就是无法使用 jq 完成它。有任何想法吗?谢谢
只是为了增加一些复杂性。假设 json 是:
{
"element1": "Test Element 1",
"element2": {
"tags": "internal",
"data": {
"data1": "Test Data 1",
"data2": "Test Data 2"
}
},
"element3": {
"function1": {
"tags": [
"new",
"internal"
]
},
"data3": "Test Data 3",
"data4": "Test Data 4"
},
"element4": {
"function2": {
"tags": "new"
},
"data5": "Test Data 5"
},
"structure1" : {
"substructure1": {
"element5": "Test Element 5",
"element6": {
"tags": "internal",
"data6": "Test Data 6"
}
}
}
}
我想得到
{
"element1": "Test Element 1",
"element4": {
"function2": {
"tags": "new"
},
"data5": "Test Data 5"
},
"structure1" : {
"substructure1": {
"element5": "Test Element 5",
}
}
}
不容易,要找到 元素 ,其中有一个 tags
键,其值要么是字符串 internal
,要么是一个数组,其中一个元素是字符串 internal
以可靠的方式仅适用于如下所示的复杂布尔表达式。
一旦找到,可以使用 del
内置删除它们。
del(.[] | first(select(recurse
| objects
| has("tags") and (.tags
| . == "internal" or (
type == "array" and index("internal")
)
)
)))
为清楚起见,以下解决方案使用辅助函数编写。辅助函数使用 any
来提高效率,并被定义为增加一点通用性。
要了解解决方案,了解 with_entries
和中缀 //
运算符会有所帮助,这两者在 jq 手册中都有解释。
# Does the incoming JSON value contain an object which has a .tags
# value that is equal to $value or to an array containing $value ?
def hasTag($value):
any(.. | select(type=="object") | .tags;
. == $value or (type == "array" and index($value)));
假设顶级 JSON 实体是一个 JSON 对象,我们现在可以简单地写:
with_entries( select( .value | hasTag("internal") | not) )
我想我想出了如何解决更复杂的案例。我现在运行:
walk(if type == "object" and has("tags") and (.tags | . == "internal" or (type == "array" and index("internal"))) then del(.) else . end) | delpaths([paths as $path | select(getpath($path) == null) | $path])
这将删除所有包含 'internal' 作为 'tag' 的元素。
我需要根据某些键值从 json 文件中删除元素。这是我要处理的文件。
{
"element1": "Test Element 1",
"element2": {
"tags": "internal",
"data": {
"data1": "Test Data 1",
"data2": "Test Data 2"
}
},
"element3": {
"function1": {
"tags": [
"new",
"internal"
]
},
"data3": "Test Data 3",
"data4": "Test Data 4"
},
"element4": {
"function2": {
"tags": "new"
},
"data5": "Test Data 5"
}
}
我想删除所有具有值为“内部”的“标签”的元素。所以结果应该是这样的:
{
"element1": "Test Element 1",
"element4": {
"function2": {
"tags": "new"
},
"data5": "Test Data 5"
}
}
我尝试了各种方法,但就是无法使用 jq 完成它。有任何想法吗?谢谢
只是为了增加一些复杂性。假设 json 是:
{
"element1": "Test Element 1",
"element2": {
"tags": "internal",
"data": {
"data1": "Test Data 1",
"data2": "Test Data 2"
}
},
"element3": {
"function1": {
"tags": [
"new",
"internal"
]
},
"data3": "Test Data 3",
"data4": "Test Data 4"
},
"element4": {
"function2": {
"tags": "new"
},
"data5": "Test Data 5"
},
"structure1" : {
"substructure1": {
"element5": "Test Element 5",
"element6": {
"tags": "internal",
"data6": "Test Data 6"
}
}
}
}
我想得到
{
"element1": "Test Element 1",
"element4": {
"function2": {
"tags": "new"
},
"data5": "Test Data 5"
},
"structure1" : {
"substructure1": {
"element5": "Test Element 5",
}
}
}
不容易,要找到 元素 ,其中有一个 tags
键,其值要么是字符串 internal
,要么是一个数组,其中一个元素是字符串 internal
以可靠的方式仅适用于如下所示的复杂布尔表达式。
一旦找到,可以使用 del
内置删除它们。
del(.[] | first(select(recurse
| objects
| has("tags") and (.tags
| . == "internal" or (
type == "array" and index("internal")
)
)
)))
为清楚起见,以下解决方案使用辅助函数编写。辅助函数使用 any
来提高效率,并被定义为增加一点通用性。
要了解解决方案,了解 with_entries
和中缀 //
运算符会有所帮助,这两者在 jq 手册中都有解释。
# Does the incoming JSON value contain an object which has a .tags
# value that is equal to $value or to an array containing $value ?
def hasTag($value):
any(.. | select(type=="object") | .tags;
. == $value or (type == "array" and index($value)));
假设顶级 JSON 实体是一个 JSON 对象,我们现在可以简单地写:
with_entries( select( .value | hasTag("internal") | not) )
我想我想出了如何解决更复杂的案例。我现在运行:
walk(if type == "object" and has("tags") and (.tags | . == "internal" or (type == "array" and index("internal"))) then del(.) else . end) | delpaths([paths as $path | select(getpath($path) == null) | $path])
这将删除所有包含 'internal' 作为 'tag' 的元素。