简体   繁体   English

如何使用 JQ 更改嵌套数组中的值?

[英]How can I use JQ to change a value in a nested array?

I'd like to change a value in a JSON file.我想更改 JSON 文件中的值。 Following is a snippet of the JSON document that shows the structure I'm trying to traverse:以下是 JSON 文档的片段,显示了我试图遍历的结构:

{
  "panels": [
    {
      "panels": [
        {
          "alert": {
            "notifications": [
              {
                "uid": "dmRej73Gz"
              }
            ]
          }
        }
      ]
    }
  ]
}

What I'd like to change我想改变什么

I'd like to change the value for all UIDs inside of the notifications array to another value.我想将通知数组中所有UID的值更改为另一个值。

I have tried the following, with no success:我尝试了以下方法,但没有成功:

cat MyJson.json |猫 MyJson.json | jq -r '.panels[] |.panels[].alert |.notifications[] |.uid |="newvalue"' jq -r '.panels[] |.panels[].alert |.notifications[] |.uid |="newvalue"'

{
  "uid": "newvalue"
}

cat MyJson.json |猫 MyJson.json | jq -r '. jq -r'。 | | select(.panels[].panels[].alert.notifications[].uid="newvalue")' select(.panels[].panels[].alert.notifications[].uid="newvalue")'

(Note UID not changed at all) (注意 UID 完全没有改变)

{
  "panels": [
    {
      "panels": [
        {
          "alert": {
            "notifications": [
              {
                "uid": "dmRej73Gz"
              }
            ]
          }
        }
      ]
    }
  ]
}

This is what I'd actually like to see:这是我真正想看到的:

{
  "panels": [
    {
      "panels": [
        {
          "alert": {
            "notifications": [
              {
                "uid": "newvalue"
              }
            ]
          }
        }
      ]
    }
  ]
}

Use Case I have Grafana dashboard that I am trying to incorporate into our CICD process.用例我有 Grafana 仪表板,我正试图将其整合到我们的 CICD 流程中。 One dashboard will be created in the Dev environment and then deployed to INT and PROD.将在 Dev 环境中创建一个仪表板,然后部署到 INT 和 PROD。

The only thing that changes from one environment to the next is the notification channel which is (unfortunately) represented as a UID.从一种环境到另一种环境的唯一变化是通知通道(不幸的是)表示为 UID。 I'm making a call to the destination Grafana site and getting the notification UID for the target environment.我正在调用目标 Grafana 站点并获取目标环境的通知 UID。 This will be used as an argument to the JQ call I'm making (what was called newvalue above).这将用作我正在进行的 JQ 调用的参数(上面称为newvalue )。 Then another JQ call will be made to change the dashboard UID.然后将进行另一个 JQ 调用以更改仪表板 UID。 Then I'll take this modified JSON and post it to the target Grafana environment using the Grafana API.然后我将使用这个修改后的 JSON 并使用 Grafana API 将其发布到目标 Grafana 环境。

If all goes well the dashboard will be created with the notification channels intact and with a unique dashboard UID.如果一切顺利,将使用完整的通知通道和唯一的仪表板 UID 创建仪表板。 Hope that's not TMI.希望那不是TMI。 :) :)

Any ideas?有任何想法吗?

You're overcomplicating:你太复杂了:

jq '.panels[].panels[].alert.notifications[].uid |= "newvalue"'

You don't want to drill down and change .您不想向下钻取和更改. (the scope for what will eventually be output), so the entire path from the top should be on the left side of the |= operator, and you don't need any | (scope 最终将输出),所以从顶部开始的整个路径应该在|=运算符的左侧,你不需要任何| . . There's no need for the -r option either.也不需要-r选项。

An alternative to @hobbs solution where we use walk() to change literally all the .uid values so we don't have to define the full path: @hobbs 解决方案的替代方案,我们使用walk()从字面上更改所有.uid,因此我们不必定义完整路径:

walk(if type == "object" and has("uid") then .uid = "NEW VALUE" else . end)

JqPlay Demo JqPlay 演示


Also, to remove the unnecessary cat we can pass the file to JQ itself:此外,要删除不必要的cat ,我们可以将文件传递给 JQ 本身:

jq 'walk(if type == "object" and has("uid") then .uid = "NEW VALUE" else . end)' MyJson.json

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM