首页 > 解决方案 > 如何通过 jq 合并来自多个文件的 JSON 数组并保留顺序

问题描述

我正在尝试设置 JSON 配置文件的层次结构,其中可以在多个级别上覆盖默认值。每个文件都是一组键/值对。其中有许多按功能按非字母顺序组织。

我找到了一种方法来获得我想要的逻辑结果,但它是按字母顺序排序的,并且由于预期参数的数量,用户很难清楚/快速地查看该集合是否是他们之前想要的使用它。

有没有办法执行这种合并,替换匹配键上的值并保留顺序?

我有这些文件:

默认.json:

[
  { "ParameterKey": "FirstStackName",  "ParameterValue": "Production-App-Database" },
  { "ParameterKey": "SecondStackName", "ParameterValue": "Production-Directory" },
  { "ParameterKey": "ThirdStackName",  "ParameterValue": "Production-VPC" },
  { "ParameterKey": "FourthStackName", "ParameterValue": "AMIFunctions" },
  { "ParameterKey": "FifthKeyName",    "ParameterValue": "administrator" },
  { "ParameterKey": "SixthUserName",   "ParameterValue": "admin" },
  { "ParameterKey": "SeventhPassword", "ParameterValue": "" }
]

环境.json:

[
  { "ParameterKey": "FirstStackName",  "ParameterValue": "Development-App-Database" },
  { "ParameterKey": "SecondStackName", "ParameterValue": "Development-Directory" },
  { "ParameterKey": "ThirdStackName",  "ParameterValue": "Development-VPC" },
  { "ParameterKey": "FifthKeyName",    "ParameterValue": "developer" }
] 

用户.json:

[
  { "ParameterKey": "FifthKeyName",    "ParameterValue": "jdoe" }
] 

安全.json:

[
  { "ParameterKey": "SeventhPassword", "ParameterValue": "secretvalue" }
] 

如果我运行这个:

jq -s '.[3] + .[2] + .[1] + .[0] | unique_by(.ParameterKey)' default.json environment.json user.json secure.json

我得到了一些有用的东西:

[
  { 
    "ParameterKey": "FifthKeyName",
    "ParameterValue": "jdoe"
  },
  {
    "ParameterKey": "FirstStackName",
    "ParameterValue": "Development-App-Database"
  },
  {
    "ParameterKey": "FourthStackName",
    "ParameterValue": "AMIFunctions"
  },
  {
    "ParameterKey": "SecondStackName",
    "ParameterValue": "Development-Directory"
  },
  {
    "ParameterKey": "SeventhPassword",
    "ParameterValue": "secretvalue"
  },
  {
    "ParameterKey": "SixthUserName",
    "ParameterValue": "admin"
  },
  {
    "ParameterKey": "ThirdStackName",
    "ParameterValue": "Development-VPC"
  }
]

但是(想象 60 个参数)它不容易被扫描为正确的,我想要的是:

[
  { "ParameterKey": "FirstStackName",  "ParameterValue": "Development-App-Database" },
  { "ParameterKey": "SecondStackName", "ParameterValue": "Development-Directory" },
  { "ParameterKey": "ThirdStackName",  "ParameterValue": "Development-VPC" },
  { "ParameterKey": "FourthStackName", "ParameterValue": "AMIFunctions" },
  { "ParameterKey": "FifthKeyName",    "ParameterValue": "jdoe" },
  { "ParameterKey": "SixthUserName",   "ParameterValue": "admin" },
  { "ParameterKey": "SeventhPassword", "ParameterValue": "secretvalue" }
] 

标签: jsonbashjq

解决方案


unique_by需要排序,所以最简单的方法是使用INDEX(大写):

[INDEX(inputs[]; .ParameterKey)[]]

我在inputs这里使用它来避免 -s 选项的所有缺点,但请记住改用 -n 选项。

如果你的 jq 没有 INDEX,你可以使用这个 def:

def INDEX(s; f):
  reduce s as $x  (null; .[$x|f] = $x );

推荐阅读