使用JavaScript连接2个具有不同主键的JSON对象

时间:2019-09-04 08:43:05

标签: javascript json

我有2个json数组,我需要将它们连接在一起。

但是如何将2个JSON数组与具有不同键值(ServerName和ComputerName)的JAvascript连接起来?

var servers = {
  0:{ServerName:"PC1", OS:"Windows", PRPName: "NO_PRP", SLA: "gold"}, 
  1:{ServerName:"PC2", OS:"Linux", PRPName: "NO_PRP", SLA: "silver"},
  2:{ServerName:"PC3", OS:"Windows", PRPName: "NO_PRP", SLA: "bronz"},
  3:{ServerName:"PC4", OS:"Windows", PRPName: "NO_PRP", SLA: "gold"}, 
  4:{ServerName:"PC5", OS:"Linux", PRPName: "NO_PRP", SLA: "bronz"},
  5:{ServerName:"PC6", OS:"Windows", PRPName: "NO_PRP", SLA: "bronz"}
};

var computers = {
  0:{Name:"PC1", location:"Amsterdam", PatchStatus: "true", RebootPending: "true"}, 
  1:{Name:"PC2", location:"London", PatchStatus: "true", RebootPending: "true"},
  2:{Name:"PC3", location:"Berlin", PatchStatus: "true", RebootPending: "false"},
  3:{Name:"PC4", location:"Berlin", PatchStatus: "false", RebootPending: "true"},
  4:{Name:"PC5", location:"London", PatchStatus: "true", RebootPending: "false"},
  5:{Name:"PC6", location:"Amsterdam", PatchStatus: "true", RebootPending: "true"}
};

结果必须为:

var endresult= {
  0:{Name:"PC1", location:"Amsterdam", PatchStatus: "true", RebootPending: "true", OS:"Windows", PRPName: "NO_PRP", SLA: "gold"}, 
  1:{Name:"PC2", location:"London", PatchStatus: "true", RebootPending: "true", OS:"Linux", PRPName: "NO_PRP", SLA: "silver"},
  2:{Name:"PC3", location:"Berlin", PatchStatus: "true", RebootPending: "false", OS:"Windows", PRPName: "NO_PRP", SLA: "bronz"},
  3:{Name:"PC4", location:"Berlin", PatchStatus: "false", RebootPending: "true", OS:"Windows", PRPName: "NO_PRP", SLA: "gold"},
  4:{Name:"PC5", location:"London", PatchStatus: "true", RebootPending: "false", OS:"Linux", PRPName: "NO_PRP", SLA: "bronz"},
  5:{Name:"PC6", location:"Amsterdam", PatchStatus: "true", RebootPending: "true", OS:"Windows", PRPName: "NO_PRP", SLA: "bronz"}
};

2 个答案:

答案 0 :(得分:2)

您可以遍历计算机阵列,并使用Array.find()通过比较名称属性来查找匹配的服务器。

然后将两个条目与spread operator合并。

var servers = {
"servers":[
  {"ServerName":"PC1", "OS":"Windows"}, 
  {"ServerName":"PC2", "OS":"Linux"},
  {"ServerName":"PC3", "OS":"Windows"}
]
}

var computers = {
"computers":[
  {"ComputerName":"PC1", "location":"Amsterdam"}, 
  {"ComputerName":"PC2", "location":"London"},
  {"ComputerName":"PC3", "location":"Berlin"}
]
}

var mergedObject = {computers: []};

for(var computer of computers.computers){

  var server = (({ OS }) => ({ OS }))(servers.servers.find(function(server){return server.ServerName === computer.ComputerName}));
  // Get only "OS" property of server
  
  var cmp = {...computer, ...server};
  mergedObject.computers.push(cmp);
}

console.log(mergedObject);


更新

根据OP的第二个问题,我将代码段更新如下:

var servers = {
  0:{ServerName:"PC1", OS:"Windows", PRPName: "NO_PRP", SLA: "gold"}, 
  1:{ServerName:"PC2", OS:"Linux", PRPName: "NO_PRP", SLA: "silver"},
  2:{ServerName:"PC3", OS:"Windows", PRPName: "NO_PRP", SLA: "bronz"},
  3:{ServerName:"PC4", OS:"Windows", PRPName: "NO_PRP", SLA: "gold"}, 
  4:{ServerName:"PC5", OS:"Linux", PRPName: "NO_PRP", SLA: "bronz"},
  5:{ServerName:"PC6", OS:"Windows", PRPName: "NO_PRP", SLA: "bronz"},
  6:{ServerName:"PC7", OS:"Windows", PRPName: "NO_PRP", SLA: "bronz"},
};

var computers = {
  0:{Name:"PC1", location:"Amsterdam", PatchStatus: "true", RebootPending: "true"}, 
  1:{Name:"PC2", location:"London", PatchStatus: "true", RebootPending: "true"},
  2:{Name:"PC3", location:"Berlin", PatchStatus: "true", RebootPending: "false"},
  3:{Name:"PC4", location:"Berlin", PatchStatus: "false", RebootPending: "true"},
  4:{Name:"PC5", location:"London", PatchStatus: "true", RebootPending: "false"},
  5:{Name:"PC6", location:"Amsterdam", PatchStatus: "true", RebootPending: "true"},
  6:{Name:"PC9", location:"Amsterdam", PatchStatus: "true", RebootPending: "true"}
};

// Please note that Objects must have a key, so I added 0, 1, 2 etc as keys.

var mergedArray = [];

for(var computer of Object.values(computers)){

  var findItem = Object.values(servers).find(function(server){return server.ServerName === computer.Name});
  if(!findItem){
    continue;
  }
  
  var {ServerName, ...server} = findItem;
  // {ServerName, ...server} is  called "desctructring". You set "ServerName" property in "ServerName" a variable 
  // and all the other properties to "server" variable
  
  var cmp = {...computer, ...server};
  mergedArray.push(cmp);
}

console.log(mergedArray);

希望这会有所帮助。

答案 1 :(得分:0)

这是我的方法。

第1步:建立一个索引。这将是一个对象,其键是每个 server ServerName属性的值,并且该值是服务器对象本身减去键-无需存储两次,并且您实际上将使用计算机中的密钥名称,而不是 server 中的密钥名称(它们是不同的:ServerName与{{ 1}})。

从一个空对象Name开始,然后为每个 server 对象添加一个将{}映射到对象本身的属性。可以使用for ... of语法来遍历数组。

索引应如下所示:

ServerName

第2步:加入。这意味着您将返回一个数组,其中{ PC1: { OS: 'Windows', PRPName: 'NO_PRP', SLA: 'gold' }, PC2: { OS: 'Linux', PRPName: 'NO_PRP', SLA: 'silver' }, PC3: { OS: 'Windows', PRPName: 'NO_PRP', SLA: 'bronz' }, PC4: { OS: 'Windows', PRPName: 'NO_PRP', SLA: 'gold' }, PC5: { OS: 'Linux', PRPName: 'NO_PRP', SLA: 'bronz' }, PC6: { OS: 'Windows', PRPName: 'NO_PRP', SLA: 'bronz' } } 数组的每个对象都将成为具有计算机的所有字段以及 server 的所有字段的对象具有匹配的computers值。我们通过访问Name找到该对象,其中index[value]value的值。

要以一种干净的方式执行此操作,我们可以使用解构从对象上剥离连接属性名称。

这里的代码实际上只有两个部分。 computer.Name用于通过属性分配来建立索引,而for ... of用于连接表。其余的只是使用destructuringspread语法来摆弄属性。

编辑:由于您在问题中更改了源数据格式和键名,因此我添加了一个名为map的实用程序函数,可将带有整数键的对象转换为数组,并更新该答案的其余部分将与您新问题的具体内容相匹配。

这是完整的可运行代码段。

arrayFromObject


关于函数式编程和性能的说明。

建立索引的更简洁的functional方法是使用Array.reduce。这也可行,但是我很奇怪它的性能不如使用var servers = { 0:{ServerName:"PC1", OS:"Windows", PRPName: "NO_PRP", SLA: "gold"}, 1:{ServerName:"PC2", OS:"Linux", PRPName: "NO_PRP", SLA: "silver"}, 2:{ServerName:"PC3", OS:"Windows", PRPName: "NO_PRP", SLA: "bronz"}, 3:{ServerName:"PC4", OS:"Windows", PRPName: "NO_PRP", SLA: "gold"}, 4:{ServerName:"PC5", OS:"Linux", PRPName: "NO_PRP", SLA: "bronz"}, 5:{ServerName:"PC6", OS:"Windows", PRPName: "NO_PRP", SLA: "bronz"} }; var computers = { 0:{Name:"PC1", location:"Amsterdam", PatchStatus: "true", RebootPending: "true"}, 1:{Name:"PC2", location:"London", PatchStatus: "true", RebootPending: "true"}, 2:{Name:"PC3", location:"Berlin", PatchStatus: "true", RebootPending: "false"}, 3:{Name:"PC4", location:"Berlin", PatchStatus: "false", RebootPending: "true"}, 4:{Name:"PC5", location:"London", PatchStatus: "true", RebootPending: "false"}, 5:{Name:"PC6", location:"Amsterdam", PatchStatus: "true", RebootPending: "true"} }; // make an array from the integer keys of an object function arrayFromObject(obj) { let array = []; for (let x in obj) { array[+x] = obj[x]; } return array; } let index = {}; for ({ ServerName, ...server } of arrayFromObject(servers) ) index[ServerName] = server; let result = arrayFromObject(computers).map( ({ Name, ...computer }) => ({ Name, ...computer, ...index[Name] })); console.log(result);,因为该实现可能会在每次迭代时构建一个新的累加器对象。我不确定您使用的JavaScript引擎是否会执行优化以防止这种情况发生。我并没有确定确切的性能,无论如何它都是特定于平台的。但这实际上是我希望使用的代码,如果它表现良好。

for ... of