嵌套Jsons的jq条件分析

ie3xauqp  于 2023-03-20  发布在  其他
关注(0)|答案(3)|浏览(98)

需要帮助解析以下嵌套Json。最终目标是从GCP获取具有非默认值的quota limits。以下是其中一个服务的示例数据(给定CPU类型的计算API)
我很难能够比较我想出了下面的,但它不工作,并返回错误.[]|select (.quota[].defaultLimit|tonumber != .quota[].effectiveLimit|tonumber)

[
  {
    "metric": "compute.googleapis.com/a2_cpus",
    "quota": [
      {
        "defaultLimit": "-1",
        "effectiveLimit": "-1"
      }
    ]
  },
  {
    "metric": "compute.googleapis.com/a2_cpus",
    "quota": [
      {
        "defaultLimit": "12",
        "effectiveLimit": "12"
      },
      {
        "defaultLimit": "12",
        "dimensions": {
          "region": "asia-east1"
        },
        "effectiveLimit": "13",
        "producerOverride": {
          "dimensions": {
            "region": "asia-east1"
          }
        }
      }
    ]
  }
]

预期的输出应该是这样的

[
  {
    "metric": "compute.googleapis.com/a2_cpus",
    "quota": [    
      {
        "defaultLimit": "12",
        "dimensions": {
          "region": "asia-east1"
        },
        "effectiveLimit": "13"
      }
    ]
  }
]

任何帮助都很感激。

uttx8gqw

uttx8gqw1#

您可以先选择具有非默认限制的所有配额,然后删除没有剩余配额的任何指标/仅保留至少具有一个配额的指标:

map(.quota |= map(select(.defaultLimit != .effectiveLimit)) | select(.quota | length > 0))

输出:

[
  {
    "metric": "compute.googleapis.com/a2_cpus",
    "quota": [
      {
        "defaultLimit": "12",
        "dimensions": {
          "region": "asia-east1"
        },
        "effectiveLimit": "13",
        "producerOverride": {
          "dimensions": {
            "region": "asia-east1"
          }
        }
      }
    ]
  }
]

仅保留限制和维度(删除producerOverride和任何其他附加属性):

map(.quota |= map(select(.defaultLimit != .effectiveLimit) | {defaultLimit, effectiveLimit, dimensions}) | select(.quota | length > 0))

输出:

[
  {
    "metric": "compute.googleapis.com/a2_cpus",
    "quota": [
      {
        "defaultLimit": "12",
        "effectiveLimit": "13",
        "dimensions": {
          "region": "asia-east1"
        }
      }
    ]
  }
]
9udxz4iz

9udxz4iz2#

根据您对问题的基本描述,以下内容似乎就足够了:

walk(if type == "object" and has("defaultLimit") 
     then select(.defaultLimit != .effectiveLimit) else . end)

但是,根据您的示例,您可能希望通过添加以下内容来扩展管道:

| walk(if type == "object" then select(.quota != []) else . end)
nnsrf1az

nnsrf1az3#

可能的解决方案:

map(
  .quota |=
    map(
      select(.defaultLimit != .effectiveLimit)
      | del(.producerOverride)
    )
  | select(.quota | length > 0)
)

工作原理

  • map(...)-因为输入是数组,map(...)将作为参数传递的表达式应用于数组的每一项,并产生包含应用于每一参数的表达式的结果的新数组;下面描述的所有后续步骤对一个对象(阵列的每个项目)进行操作。
  • .quota |= map(...)-属性.quota的值(它是一个数组)被传递到map()(它产生一个新数组)并且结果数组被存储回.quota;这和.quota = (.quota | map(...))是一样的,但是它更短,更容易阅读。
  • map(select(...) | del(...))-对于.quota数组的每个项目,运行select(.defaultLimit != .effectiveLimit),然后从返回的对象(如果存在)中删除(del)属性.producerOverride。结果是一个仅包含非默认值配额条目的数组。
  • select(.defaultLimit != .effectiveLimit)-如果满足条件,则生成输入对象,否则不生成任何内容。这是过滤具有非默认值的配额项的方式。
  • del(.producerOverride)-此过滤器在此,因为属性.producerOverride未显示在预期输出中。如果输入对象可能包含此处未列出的其他属性,并且您希望在输出中仅保留一组已知属性,则改用此过滤器:
| { defaultLimit, dimensions, effectiveLimit }

但是要注意,这个函数产生的对象总是具有这三个属性,即使不是所有的属性都在输入中(dimensions并不存在于输入中的所有quota项中),在这个例子中,这些属性的值是null

  • | select(.quota | length > 0)-此过滤器在输入数组的对象的.quota属性经过如上所述的处理后,在输入处获取这些对象。它只保留具有非空.quota属性的对象。前面的过滤器从第一个输入项生成如下所示的项:
{
   "metric": "compute.googleapis.com/a2_cpus",
   "quota": []
}

此过滤器删除此类项目。

jq文档

有关详细信息,请阅读jq tutorialjq manual

相关问题