首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用jq基于公共密钥值对合并两个JSON文件

使用jq基于公共密钥值对合并两个JSON文件
EN

Stack Overflow用户
提问于 2019-11-29 12:00:44
回答 1查看 1.4K关注 0票数 1

我有两个具有以下结构的JSON文件

File1.json

代码语言:javascript
复制
{
  "Plugins": [
               {
                 "Name": "Plugin A",
                 "Installation": [
                  {
                    "Version": "1.0",
                    "Server" : "abc"
                  }
                  ]
               },
               {
                  "Name": "Plugin B",
                  "Installation": [
                   {
                     "Version": "2.0",
                     "Server" : "abc"
                   }
                   ]
               },
               {
                  "Name": "Plugin C",
                  "Installation": [
                   {
                     "Version": "2.0",
                     "Server" : "abc"
                   }
                   ]
               }
   ]
}

File2.json

代码语言:javascript
复制
{
  "Plugins": [
               {
                 "Name": "Plugin A",
                 "Installation": [
                  {
                    "Version": "1.1",
                    "Server" : "xyz"
                  }
                  ]
               },
               {
                  "Name": "Plugin B",
                  "Installation": [
                   {
                     "Version": "2.0",
                     "Server" : "xyz"
                   }
                   ]
                },
   ]
}

我想把它们合并,得到这样的输出

代码语言:javascript
复制
{
  "Plugins": [
               {
                 "Name": "Plugin A",
                 "Installation": [
                  {
                    "Version": "1.0",
                    "Server" : "abc"
                  },
                  {
                    "Version": "1.1",
                    "Server" : "xyz"
                  }
                  ]
               },
               {
                  "Name": "Plugin B",
                  "Installation": [
                   {
                     "Version": "2.0",
                     "Server" : "abc"
                   },
                   {
                     "Version": "2.0",
                     "Server" : "xyz"
                   }
                   ]
               },
               {
                  "Name": "Plugin C",
                  "Installation": [
                   {
                     "Version": "2.0",
                     "Server" : "abc"
                   }
                   ]
               }
   ]
}

这两个JSON文件具有完全相同的结构,但仅在文件中的内容方面有所不同。我主要考虑使用jq实用工具。Shell或jenkins-groovy脚本也可以。任何帮助都将不胜感激!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-11-29 13:30:04

有一种方法可以做到:

代码语言:javascript
复制
def mergePlugin($plugin):
  if .[$plugin.Name]
  then .[$plugin.Name].Installation += $plugin.Installation
  else .[$plugin.Name] = $plugin
  end;

{
  "Plugins": (
    map(.Plugins)
    | add
    | reduce .[] as $plugin ({}; mergePlugin($plugin))
    | to_entries | map(.value)
  )
}

运行此命令:

代码语言:javascript
复制
jq -s -f mergePlugins.jq File*.json

命令-ine论点解释如下:

--slurp / -s:与其为输入中的每个JSON对象运行过滤器,不如将整个输入流读入一个大数组中,只运行一次过滤器。 -f filename / --from-file filename:从文件而不是命令行读取过滤器,比如awk的-f选项。您还可以使用´#´进行注释。

这个jqplay片段通过提供对象列表作为输入而不是多个对象来模拟-s

下面是解决方案的工作原理:jq -s '.' File*.json提供了一个{"Plugins": [...]}对象列表。由于对[...]部件感兴趣,jq -s 'map(.Plugins)' File*.json提供了以下列表(每个文件一个):

代码语言:javascript
复制
[
  [
    {
      "Name": "Plugin A",
      ...
    },
    {
      "Name": "Plugin B",
      ...
    },
    {
      "Name": "Plugin C",
      ...
    }
  ],
  [
    {
      "Name": "Plugin A",
      ...
    },
    {
      "Name": "Plugin B",
      ...
    }
  ]
]

我们可以使用jq -s 'map(.Plugins) | add' File*.json折叠一层嵌套列表。

代码语言:javascript
复制
[
  {
    "Name": "Plugin A",
    ...
  },
  {
    "Name": "Plugin B",
    ...
  },
  ...
]

对于下一部分,由于我希望将所有的"Name": "Plugin X"合并在一起,所以我认为一个字典/对象(键是"Plugin X" )将是一个很好的数据结构,因为对于每个插件,如果我以前是否遇到它,我可以做一个固定时间的查找。

我使用reduce构建了这个字典

代码语言:javascript
复制
reduce .[] as $plugin ({}; ...some expression using '.' and '$plugin'...)

{}是这个对象的初始值,$plugin是每个{"Name": "Plugin X", "Installation": [...]}值,而.是中间字典/对象,包含键是"Plugin X",值是$plugin-like对象。

因为如果-然后这个过滤器有两样东西:.$plugin

这就产生了:

代码语言:javascript
复制
{
  "Plugin A": {
    "Name": "Plugin A",
    "Installation": [
      {
        "Version": "1.0",
        "Server": "abc"
      },
      {
        "Version": "1.1",
        "Server": "xyz"
      }
    ]
  },
...
}

这几乎是最后的结果,只是有一个不必要的{"Plugin A": {...}}包装器现在可以废弃,还有一个缺少的{"Plugins": [...]}包装器需要重新添加。

改进的想法:

  • 我很肯定你能做一些比 { "Plugins": ( ... | to\_entries | map(.value) ) } 这是最后一部分,但它完成了任务。
  • 我还认为,实际的合并可以做的时间比如果-然后-否则。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59104389

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档