Json jq-仅从数组中选择并筛选某些对象

Json jq-仅从数组中选择并筛选某些对象,json,select,jq,Json,Select,Jq,我的JSON文件具有以下结构 [ { "Header": { "Tenant": "T1" }, "Body": [ { "agentTechnologyType": "JAVA", "entityId

我的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[]数组对象中:

仅选择.Body[]数组中不存在.webServerName键的这些对象-此条件应仅将对象2保留在.Body[]数组中 仅在.Body[]数组中选择这些对象,其中.webServerName的值为www.example.com:443-这将保留对象0,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"
      }
    ]
  }
]
第三种情况如下:

[
  {
    "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") ))
你的两次尝试虽然有效,但确实令人费解。有选择地过滤掉数组中的对象的标准模式是对右选择表达式使用|=运算符

|{Tenant:$x,Body:[$y]}是错误的,因为它应用于在上一个表达式中筛选的两个对象中的每一个。因此,每个结果都创建了一个租户字段。由于您没有更改同一密钥租户的密钥名称,因此使用{..}重新创建新对象是毫无意义的。

谢谢。我的问题-为什么。webServerName!=www.example.com:443生成的输出包含的对象内部没有键WebServerName?我知道我可以使用null包含额外的过滤器,但我想了解其机制。