【问题标题】:How can I use JQ to change a value in a nested array?如何使用 JQ 更改嵌套数组中的值?
【发布时间】:2021-05-25 18:22:07
【问题描述】:

我想更改 JSON 文件中的值。以下是 JSON 文档的 sn-p,显示了我正在尝试遍历的结构:

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

我想改变什么

我想将 notifications 数组中所有 UID 的值更改为另一个值。

我尝试了以下方法,但没有成功:

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

{
  "uid": "newvalue"
}

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

(注意 UID 完全没有改变)

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

这是我真正希望看到的:

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

用例 我有 Grafana 仪表板,我正试图将其整合到我们的 CICD 流程中。将在 Dev 环境中创建一个仪表板,然后部署到 INT 和 PROD。

从一种环境到另一种环境的唯一变化是通知通道(不幸的是)表示为 UID。我正在调用目标 Grafana 站点并获取目标环境的通知 UID。这将用作我正在进行的 JQ 调用的参数(上面称为 newvalue)。然后将进行另一个 JQ 调用以更改仪表板 UID。然后,我将使用 Grafana API 将修改后的 JSON 发布到目标 Grafana 环境。

如果一切顺利,将使用完整的通知渠道和唯一的仪表板 UID 创建仪表板。希望那不是TMI。 :)

有什么想法吗?

【问题讨论】:

    标签: json jq


    【解决方案1】:

    你太复杂了:

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

    您不想向下钻取并更改.(最终输出的范围),因此从顶部开始的整个路径应该在@的左侧987654323@ 运算符,您不需要任何|。也不需要-r 选项。

    【讨论】:

    • 谢谢!我已经习惯了使用“-r”,我不知道我在那里。你是对的,不需要。这行得通。我现在遇到的事情是,当我将它应用于整个(真实)json 文档时,我遇到了可怕的“无法迭代 null (null)”错误。可能是其中一个 Alerts 对象缺少 Notifications 数组。我知道您可以使用 Select 检查数组长度,但我不确定它是否适用于我正在使用的格式。
    • @KSS 在这种情况下,您可以尝试 0stone0 的解决方案,或者您可以尝试将所有 [] 替换为 []?,这将忽略空值而不是尝试将它们视为数组。
    • 这行得通! ".panels[].panels[]?.alert.notifications[]?.uid |= "newvalue"" - 再次感谢!
    【解决方案2】:

    @hobbs solution 的替代方法,我们使用walk() 来更改实际上所有.uid,因此我们不必定义完整路径:

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

    JqPlay Demo


    另外,要删除unnecessary cat,我们可以将文件传递给 JQ 本身:

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

    【讨论】:

    • 谢谢。它完美地工作。但是更改了所有的 UID,看起来 walk 不允许您指定特定的路径来开始步行。但是,对于我正在尝试做的事情可能没问题。所有通知 UID 都会更改,唯一的其他 UID 是仪表板本身的 UID。碰巧,我还需要更改该 UID,因此再进行一次编辑和更改仪表板 UID 将是一件简单的事情。这可能是解决方案。
    • 很高兴它有帮助!您能否举例说明您正在尝试做的事情?
    • 我刚刚在原始帖子中添加了一个用例部分。希望对您有所帮助。
    • 了解您的用例,但很难想象 JSON 以及您希望如何格式化它。
    • 不需要格式化。它是由 Grafana 生成的,我所做的只是改变它的一些值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-20
    • 2020-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多