json - 如何在基于字段值替换项目的同时在 jq 中输出整个文档?

标签 json jq amazon-cloudfront aws-cli edit

我正在尝试使用 jq 来解析 AWS CloudFront 配置 JSON 文件并更改一些值,以便我可以使用该配置发出更新语句。
文件
具有编辑值的重要文档格式片段是:

{
    "ETag": "REDACTED",
    "DistributionConfig": {
        "Origins": {
            "Quantity": 2,
            "Items": [
                {
                    "Id": "redacted-1",
                    "DomainName": "redacted1.us-east-1.amazonaws.com",
                    "OriginPath": "/redacted"
                },
                {
                    "Id": "redacted-2",
                    "DomainName": "redacted2.s3.amazonaws.com",
                    "OriginPath": ""
                }
            ]
        }
    }    
}
我想做什么
我想输出整个文档,但是:
  • 我想设置ETag值到 ""
  • 在 items 数组中的第二个项目上,我想设置 OriginPath到我选择的值

  • (这是为了支持我们的 CI/CD 流程能够将 CloudFront 分发指向 S3 存储桶中刚刚部署的代码的新文件夹。我想以这些特定方式修改现有配置,但保持其余部分不变。 )
    有用的东西……有点. | (.DistributionConfig.Origins.Items[1].OriginPath = "Hello") | .ETag = "" 的 jq 过滤器做我需要它做的事情,导致:
    {
      "ETag": "", // correctly updated
      "DistributionConfig": {
        "Origins": {
          "Quantity": 2, // correctly retained
          "Items": [
            {
              "Id": "redacted-1",
              "DomainName": "redacted1.us-east-1.amazonaws.com",
              "OriginPath": "/redacted"
            },
            {
              "Id": "redacted-2",
              "DomainName": "redacted2.s3.amazonaws.com",
              "OriginPath": "Hello" // correctly updated
            }
          ]
        }
      }
    }
    
    我遇到问题的地方
    上面的解决方案有效......只要我指的是数组中的第二项。但我并不总是确定它会是数组中的第二项。
    所以相反,我想根据 Id 进行匹配属性(property)。
    我能够找到的任何解决方案似乎都是将文档过滤到 JSON 的那部分,而不是匹配和更新值作为输出文档的一部分。

    如何过滤具有特定值的字段的数组,并仍然输出整个文档?
    或者换一种方式 - 鉴于上面的文件,我该如何更改:
    . | (.DistributionConfig.Origins.Items[1].OriginPath = "Hello") | .ETag = ""
    
    对于让我引用的东西.Id="redaacted-2"而不是 Items[1] ?
    演示链接
    脚本演示在 https://jqplay.org/s/ZQ7XcM5-BY万一有人想尝试答案。

    最佳答案

    完成此类编辑的基本方法是使用以下语法:

    PATHSPEC = VALUE
    
    或者如果该值以某种方式取决于 PATHSPEC:
    PATHSPEC |= VALUE
    
    其中 PATHSPEC 是 jq 路径规范。
    使用这个原则,在你的情况下,你可以写:
    .ETag = ""
    | .DistributionConfig.Origins.Items[1].OriginPath = "myvalue"
    
    或者,如果您想基于 .Id 进行第二次更新:
    .ETag = ""
    | .DistributionConfig.Origins.Items[] |=
       if .Id == "redacted-2" then .OriginPath = "myvalue" else . end
    
    上面的例子可以在 https://jqplay.org/s/u5xbhbSs4l 上看到。
    变化
    当然有许多变化。例如,您可以使用 .Quantity 作为要更新的项目的索引:
    .ETag = ""
    | .DistributionConfig.Origins.Quantity as $ix
    | .DistributionConfig.Origins.Items[$ix - 1].OriginPath = "myvalue"
    
    或更干:
    .ETag = ""
    | .DistributionConfig.Origins |=
        (.Items[.Quantity  - 1].OriginPath = "myvalue")
    
    

    关于json - 如何在基于字段值替换项目的同时在 jq 中输出整个文档?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68074046/

    相关文章:

    javascript - 从 api 获取数据后在 React 中显示嵌套对象?

    javascript - javascript 创建的 JSON-LD 不显示在 View 源中

    json - 如何舍入、地板、天花板、截断

    linux - 解析错误 : Invalid numeric literal at EOF at line 1, 列 10897

    jq - 使用 jq 一次删除多个键

    amazon-web-services - 如何使用 CloudFront 从 AWS S3 安全地播放 .m3u8 流文件?

    amazon-s3 - 规划可扩展的 Web 应用程序的开发

    javascript - 按自定义数组对 JSON 对象进行排序

    amazon-web-services - Cloudfront TTL 不起作用

    javascript - json 解析 - 取消转义引号