首页 > 解决方案 > 如何使用 jq 加入 json 文件?

问题描述

我有以下 json 文件

[
  {
    "clusterName": "cluster1",
    "nodes": [
      {
        "hostname": "server1",
        "dse": "6.7.5"
      },
      {
        "hostname": "server2",
        "dse": "6.7.5"
      }
    ]
  },
  {
    "clusterName": "cluster2",
    "nodes": [
      {
        "hostname": "server3",
        "dse": "6.7.5"
      },
      {
        "hostname": "server4",
        "dse": "6.7.5"
      }
    ]
  }
]

我还有另一个 json

[
  {
    "hostname": "server1",
    "memorysize": "47.01 GiB",
    "processorcount": 12
  },
  {
    "hostname": "server2",
    "memorysize": "47.01 GiB",
    "processorcount": 12
  },
  {
    "hostname": "server3",
    "memorysize": "47.01 GiB",
    "processorcount": 10
  },
  {
    "hostname": "server4",
    "memorysize": "47.01 GiB",
    "processorcount": 11
  },
  {
    "hostname": "server5",
    "memorysize": "47.01 GiB",
    "processorcount": 12
  },
  {
    "hostname": "server6",
    "memorysize": "47.01 GiB",
    "processorcount": 12
  }
]

我想加入这两个 json 以产生以下输出

[
  {
    "clusterName": "cluster1",
    "nodes": [
      {
        "hostname": "server1",
        "dse": "6.7.5",
        "memorysize": "47.01 GiB",
        "processorcount": 12
      },
      {
        "hostname": "server2",
        "dse": "6.7.5",
        "memorysize": "47.01 GiB",
        "processorcount": 12
      }
    ]
  },
  {
    "clusterName": "cluster2",
    "nodes": [
      {
        "hostname": "server3",
        "dse": "6.7.5",
        "memorysize": "47.01 GiB",
        "processorcount": 10
      },
      {
        "hostname": "server4",
        "dse": "6.7.5",
        "memorysize": "47.01 GiB",
        "processorcount": 11
      }
    ]
  }
]

基本上第一个文件有集群字典的列表。有节点,我有第二个文件,其中包含节点字典列表。

提到的解决方案不适用于多个集群。

有没有更好的办法在 python 中做到这一点?

标签: jsonlinuxjq

解决方案


使用的解决方案jq

<file1 jq --slurpfile f file2 '
  {
     clusterName:.[].clusterName,
     nodes:map($f[],.nodes)|add|group_by(.hostname)|map(add)
  }'

这将使用这两个文件构建一个对象。
第一个字段clusterName取自第二个文件的相同字段。
第二个字段nodes是基于hostname(用group_by命令完成)两者的对象组合


对以下评论的暂定回答:
我认为这-s在这里没有任何优势,因为您需要内存中的两个文件(而不是 1 和--slurpfile)。
为了不使用索引,我们的想法是在使用之前测试该字段是否存在。您可以使用?and//运算符执行此操作。他们一起从一种if not ... then ...。这是一个可能的解决方案:

jq -s '{
   clusterName:(.[][].clusterName?//empty),
   nodes:map(.[].nodes[]?//.[])|group_by(.hostname)|map(add)
}' file1 file2

如您所见,两个脚本的难点在于“规范化”对象以执行group_by操作。


推荐阅读