使用jq将新密钥对附加到JSON文件

时间:2017-03-15 18:28:35

标签: json bash jq

我已经阅读了几乎所有可以在SO上找到的问题,并且有相同的一般前提,而且我已经接近了三次不同的时间,但我无法做到这一点。

给定一个名为parameters.json的JSON文件,其密钥对如此; (缩短为分享目的)

[
  {
    "ParameterKey": "Foo1",
    "ParameterValue": "Bar1"
  },
  {
    "ParameterKey": "Foo2",  
    "ParameterValue": "Bar2"
  }
]

我想添加另一个密钥对,比如说

  {
    "ParameterKey": "Foo3",
    "ParameterValue": "Bar3"
  }

所以我最终得到了像

这样的文件
[
  {
    "ParameterKey": "Foo1",
    "ParameterValue": "Bar1"
  },
  {
    "ParameterKey": "Foo2",  
    "ParameterValue": "Bar2"
  },
  {
    "ParameterKey": "Foo3",
    "ParameterValue": "Bar3"
  }
]

使用案例&尝试

我正在编写一个复制和更新AWS参数文件的bash脚本 - 这是密钥对的来源。我们有一个新的密钥对,需要在复制后添加到任何现有文件中。我可以得到if / then然后做得很好,它实际上添加了新的密钥对,这让我很难过。

随着大量的谷歌搜索,我最终得到了这个笨重的解决方法,我不太了解,虽然它生成了密钥对,但是没有将它添加回参数.json

item='{"ParameterKey": "RTSMSnapshotID"}'

jq --argjson item "$item" '$item + {"ParameterValue": ""}' parameters.json

我在命令行上正确地将密钥对打印回来,所以我想添加| sponge parameters.json,但这会给我一个空文件。

我还考虑了一个sed解决方法,它修剪了文件的最后一行,然后添加了新的密钥对(和EOF),但当然sed并没有很好地使用换行符,我无法得到它工作。

我对使用bash中的任何内容以及jq中的任何内容的解决方案持开放态度。我仍然是bash / jq noob,所以我们非常感谢您的详细解释。

2 个答案:

答案 0 :(得分:2)

使用argjson的想法是正确的,但语法如下jq-1.5

jq --argjson obj '{ "ParameterKey": "Foo3", "ParameterValue": "Bar3" }' '. + [$obj]' < json 
[
  {
    "ParameterKey": "Foo1",
    "ParameterValue": "Bar1"
  },
  {
    "ParameterKey": "Foo2",
    "ParameterValue": "Bar2"
  },
  {
    "ParameterKey": "Foo3",
    "ParameterValue": "Bar3"
  }
]

查看jq-documentation,了解有关++=运营商的详情。

我不知道如何在jq本身中执行此操作,但您可以使用简洁的bash技巧来执行此操作,

jq --argjson obj '{ "ParameterKey": "Foo3", "ParameterValue": "Bar3" }' '. + [$obj]' < json > temp && mv temp json

答案 1 :(得分:1)

如果你有一个带有JSON数组的文件(比如parameters.json),以及一个或多个带有JSON实体的附加文件(比如文件* .json),你想要在第一个文件中追加到数组,如果你想覆盖第一个文件,这是一个相当狡猾的解决方案,但需要jq 1.5或更高版本:

$ jq 'reduce inputs as $in (.; . + [$in])' parameters.json file*.json |
    sponge parameters.json

请注意,使用此方法,每个辅助文件中的每个顶级JSON实体将分别附加到数组中。

使这有点狡猾的原因是inputs在没有-n选项的情况下使用。

由于您提到bash,请注意,如果任何“file * .json”来源是一个过程,您可以使用<( ... )而不是指定文件名,例如:

$ jq 'reduce inputs as $in (.; . + [$in])' parameters.json <(curl -Ss ...) |
    sponge parameters.json

如果您没有sponge,那么您可以使用这个成语:

jq ..... > OUT && mv IN OUT