jq-只从数组中选择和筛选某些对象



我的JSON文件具有以下结构

[
{
"Header": {
"Tenant": "T1"
},
"Body": [
{
"agentTechnologyType": "JAVA",
"entityId": "SERVICE-EDA448F07EDBDAA6",
"serviceType": "WebRequest",
"webServerName": "www.example.com:443"
},
{
"agentTechnologyType": "TOMCAT",
"entityId": "SERVICE-728B1FF49D132C89",
"serviceType": "WebRequest",
"webServerName": "www.example.com:80"
},
{
"agentTechnologyType": "JAVA",
"entityId": "SERVICE-42A0FB8666B36EB4",
"serviceType": "Process"
},
{
"agentTechnologyType": "APACHE",
"serviceType": "WebRequest",
"webServerName": "www.example.com:443"
}
]
}
]

我需要应用几个过滤器,并根据不同的标准留在.Body[]数组对象中:

  1. 仅选择.Body[]数组中不存在.webServerName键的这些对象-此条件应仅保留.Body[]数组中的对象#2
  2. 仅在.Body[]数组中选择这些对象,其中.webServerName的值为www.example.com:443,这将留下对象#0.3
  3. 选择存在.webServerName键的所有对象,因此否定条件#1-这将保留除#2之外的所有对象

对于#1,下面的过滤器完成的工作

[.[].Header as $x |  (.[].Body[] | select( (.webServerName == null  ))) as $y | {Tenant: $x, Body: [$y]} ]

它给出以下输出:

[
{
"Tenant": {
"Tenant": "T1"
},
"Body": [
{
"agentTechnologyType": "JAVA",
"entityId": "SERVICE-42A0FB8666B36EB4",
"serviceType": "Process"
}
]
}
]

但当我试图修改条件#2 的过滤器时

[.[].Header as $x |  (.[].Body[] | select( (.webServerName == "www.example.com:443"  ))) as $y | {Tenant: $x, Body: [$y]} ] 

这给了我以下输出——两个条目而不是一个条目。

[
{
"Tenant": {
"Tenant": "T1"
},
"Body": [
{
"agentTechnologyType": "JAVA",
"entityId": "SERVICE-EDA448F07EDBDAA6",
"serviceType": "WebRequest",
"webServerName": "www.example.com:443"
}
]
},
{
"Tenant": {
"Tenant": "T1"
},
"Body": [
{
"agentTechnologyType": "APACHE",
"serviceType": "WebRequest",
"webServerName": "www.example.com:443"
}
]
}
]

而预期的输出应该看起来像案例#2:

[
{
"Tenant": {
"Tenant": "T1"
},
"Body": [
{
"agentTechnologyType": "JAVA",
"entityId": "SERVICE-EDA448F07EDBDAA6",
"serviceType": "WebRequest",
"webServerName": "www.example.com:443"
},
{
"agentTechnologyType": "APACHE",
"serviceType": "WebRequest",
"webServerName": "www.example.com:443"
}
]
}
]

对于案例#3,如下所示:

[
{
"Header": {
"Tenant": "T1"
},
"Body": [
{
"agentTechnologyType": "JAVA",
"entityId": "SERVICE-EDA448F07EDBDAA6",
"serviceType": "WebRequest",
"webServerName": "www.example.com:443"
},
{
"agentTechnologyType": "TOMCAT",
"entityId": "SERVICE-728B1FF49D132C89",
"serviceType": "WebRequest",
"webServerName": "www.example.com:80"
},
{
"agentTechnologyType": "APACHE",
"serviceType": "WebRequest",
"webServerName": "www.example.com:443"
}
]
}
]

我试图弄清楚我在哪里犯了错误——在选择条件或最后形成新对象时。

根据您的需求判断,您似乎需要一个表达式来选择.Body[]数组中.webServerName密钥为www.example.com:443或密钥基本存在的对象

.[].Body |= map(select(.webServerName == "www.example.com:443" or has("webServerName") ))

你的两次尝试虽然有效,但确实令人费解。有选择地过滤掉数组内对象的标准模式是将|=运算符与正确的select表达式一起使用。

| {Tenant: $x, Body: [$y]}是错误的,因为它应用于在上一个表达式中筛选的2个对象中的每一个。因此,每个结果都创建了一个Tenant字段。由于密钥名称没有更改(相同的密钥Tenant(,因此实际上没有用{..}重新创建新对象的目的。

最新更新