meallhour
meallhour

Reputation: 15599

How to combine 2 Json objects into a single Json object using NodeJS?

I have 3 JSON objects as defined below:

 const totalData = [{ Hostname: "abc123", name: "CName-A", Status: "PASS", Heading: "Not Applicable" },
            { Hostname: "abc123", name: "CName-B", Status: "FAIL", Heading: "Not Applicable" },
            { Hostname: "abc235", name: "CName-C", Status: "FAIL", Heading: "Not Applicable" },
            { Hostname: "abc235", name: "CName-D", Status: "FAIL", Heading: "Not Applicable" }];

const otherTotalData = [{ Hostname: "abc123", name: "QName-A", Status: "PASS", Heading: "HeadingQA" },
            { Hostname: "abc123", name: "QName-B", Status: "FAIL", Heading: "HeadingQB" },
            { Hostname: "abc235", name: "QName-C", Status: "FAIL", Heading: "Not Applicable" },
            { Hostname: "abc235", name: "QName-D", Status: "FAIL", Heading: "Not Applicable" }];

const newTotalData = [{ Hostname: "abc123", name: "TName-A", Status: "PASS", Heading: "HeadingTA" },
            { Hostname: "abc123", name: "TName-B", Status: "FAIL", Heading: "HeadingTB" },
            { Hostname: "abc235", name: "TName-C", Status: "FAIL", Heading: "Not Applicable" },
            { Hostname: "abc235", name: "TName-D", Status: "FAIL", Heading: "Not Applicable" }];                

I have a function which uses array reduce method:

function createArray(totalData) {
const keyValues = ["Status", "Heading"],
    result = Object.values(totalData.reduce((res, { Hostname, name, ...o }) => {
        res[Hostname] = res[Hostname] || { Hostname };
        keyValues.forEach(k => res[Hostname][name + k] = o[k]);
        return res;
    }, {}));
}

Now, I am calling the two functions:

const Res1 = createArray(totalData);

const Res2 = createArray(otherTotalData);

const Res3 = createArray(newTotalData);

Here Res1 has the output:

[
    {
    "Hostname": "abc123",
    "CName-AStatus": "PASS",
    "CName-BStatus": "FAIL"
    },
    {
    "Hostname": "abc235",
    "CName-CStatus": "FAIL",
    "CName-DStatus": "FAIL"
    }
]

And, Res2 has the output:

[
    {
    "Hostname": "abc123",
    "QName-AStatus": "PASS",
    "QName-BStatus": "FAIL"
    },
    {
    "Hostname": "abc235",
    "QName-CStatus": "FAIL",
    "QName-DStatus": "FAIL"
    }
]

And, Res3 has the output:

[
    {
    "Hostname": "abc123",
    "TName-AStatus": "PASS",
    "TName-BStatus": "FAIL"
    },
    {
    "Hostname": "abc235",
    "TName-CStatus": "FAIL",
    "TName-DStatus": "FAIL"
    }
]

I want to combine Res1, Res2 and Res3 such that the final Json object looks as following:

[
    {
    "Hostname": "abc123",
    "CName-AStatus": "PASS",
    "CName-BStatus": "FAIL",
    "QName-AStatus": "PASS",
    "QName-BStatus": "FAIL",
    "TName-AStatus": "PASS",
    "TName-BStatus": "FAIL"
    },
    {
    "Hostname": "abc235",
    "CName-CStatus": "FAIL",
    "CName-DStatus": "FAIL",
    "QName-CStatus": "FAIL",
    "QName-DStatus": "FAIL",
    "TName-CStatus": "FAIL",
    "TName-DStatus": "FAIL"
    }
]

How can I combine Res1 Res2 and Res3?

Upvotes: 0

Views: 59

Answers (2)

Eldar
Eldar

Reputation: 10790

Basically you can search the other array with shared property: "Hostname" and use Object.assign to combine two objects together.

const res1 = [{
    "Hostname": "abc123",
    "CName-AStatus": "PASS",
    "CName-BStatus": "FAIL"
  },
  {
    "Hostname": "abc235",
    "CName-CStatus": "FAIL",
    "CName-DStatus": "FAIL"
  }
];

const res2 = [{
    "Hostname": "abc123",
    "QName-AStatus": "PASS",
    "QName-BStatus": "FAIL"
  },
  {
    "Hostname": "abc235",
    "QName-CStatus": "FAIL",
    "QName-DStatus": "FAIL"
  }
];

const res3 = [{
    "Hostname": "abc123",
    "TName-AStatus": "PASS",
    "TName-BStatus": "FAIL"
  },
  {
    "Hostname": "abc235",
    "TName-CStatus": "FAIL",
    "TName-DStatus": "FAIL"
  }
];

function mergeAll(key, ...args) {
  const arr = Array.from(args);
  const first = arr[0];
  const rest = arr.slice(1);

  return first.map(r => Object.assign({}, r, ...rest.map(q => q.find(t => t[key] === r[key]))));
}

const result = mergeAll('Hostname', res1, res2, res3);
console.log(result);

Edit: As Op mentioned in the comments there are 3 results to merge so I made a generalized method for any number of results.

Upvotes: 1

Code Maniac
Code Maniac

Reputation: 37755

You can just map over one array and use index to get respective value from another array and merge values

let res1 = [{"Hostname": "abc123","CName-AStatus": "PASS","CName-BStatus": "FAIL"},{"Hostname": "abc235","CName-CStatus": "FAIL","CName-DStatus": "FAIL"}]
let res2 = [{"Hostname": "abc123","QName-AStatus": "PASS","QName-BStatus": "FAIL"},{"Hostname": "abc235","QName-CStatus": "FAIL","QName-DStatus": "FAIL"}]

let final = res1.map((inp, index) => {
  return { ...inp,
    ...res2[index]
  }
})

console.log(final)

P.S:- This considers the arrays are sorted in same order and always a respective value is present in other array. ( considering your given example data ). If that is not the case then we just need to find the respective value from other array based on some property and the merge.

let res1 = [{"Hostname": "abc123","CName-AStatus": "PASS","CName-BStatus": "FAIL"},{"Hostname": "abc235","CName-CStatus": "FAIL","CName-DStatus": "FAIL"}]
let res2 = [{"Hostname": "abc235","QName-CStatus": "FAIL","QName-DStatus": "FAIL"},{"Hostname": "abc123","QName-AStatus": "PASS","QName-BStatus": "FAIL"}]


let final = [...res1,...res2].reduce((op,inp)=>{
  let key = inp.Hostname
  if(op.has(key)){
    op.set(key, {...op.get(key), ...inp} )
  } else{
    op.set(key, inp)
  }
  return op
}, new Map())

console.log([...final.values()])

Upvotes: 1

Related Questions