Reputation: 15
I want to compare two JSON files and output only the newly added objects based on their "Id". I also need to ignore changes in the position of the objects within the JSON file (I don't want to compare line changes).
You'll notice in the code below that Greg's age has changed - I don't want to include these sort of (Key:Value) changes in my output either.
I'm currently using a package called json-diff.
Here's my current code:
const jsonDiff = require('json-diff');
var oldJson = {
"data": [
{
"Id": "2",
"Name": "Greg",
"ranges": [
{
"age": "70"
}
]
},
{
"Id": "1",
"Name": "Tom",
"ranges": [
{
"age": "10"
}
]
}
]
};
var newJson = {
"data": [
{
"Id": "2",
"Name": "Greg",
"ranges": [
{
"age": "20" // Even though Greg's age has changed, I don't want it in my output
}
]
},
{
"Id": "3",
"Name": "Bob",
"ranges": [
{
"age": "30"
}
]
},
{
"Id": "1",
"Name": "Tom",
"ranges": [
{
"age": "10"
}
]
}
]
};
function compare(newJson, oldJson) {
let rawDiff = jsonDiff.diff(newJson.data, oldJson.data);
let prettyDiff = JSON.stringify(rawDiff).replace(/,\[" "]/g, '');
console.log(prettyDiff);
}
compare(newJson, oldJson);
Current output:
[
[
"~",
{
"ranges": [
[
"-",
{
"age": "20"
}
],
[
"+",
{
"age": "70"
}
]
]
}
],
[
"-",
{
"Id": "3",
"Name": "Bob",
"ranges": [
{
"age": "30"
}
]
}
]
]
Required output:
{
"data": [
{
"Id": "3",
"Name": "Bob",
"ranges": [
{
"age": "30"
}
]
}
]
}
Upvotes: 1
Views: 5557
Reputation: 21
For those who need to solve a more complex problem:
function compareJsonArrays(currentArray, newArray) {
const diff = {
newItems: [],
deletedItems: [],
updatedItems: []
};
const currentMap = new Map(currentArray.map(item => [item.url, item]));
const newMap = new Map(newArray.map(item => [item.url, item]));
for (const [url, newItem] of newMap) {
if (!currentMap.has(url)) {
diff.newItems.push(newItem);
} else {
const currentItem = currentMap.get(url);
if (!compareObjects(newItem, currentItem)) {
diff.updatedItems.push(newItem);
}
}
}
for (const [url, currentItem] of currentMap) {
if (!newMap.has(url)) {
diff.deletedItems.push(currentItem);
}
}
return diff;
}
function compareObjects(obj1, obj2) {
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) {
return false;
}
for (const key of keys1) {
if (obj1[key] !== obj2[key]) {
return false;
}
}
return true;
}
Upvotes: 0
Reputation: 1648
i'm not sure if this is your need but
var oldJson = {
"data": [
{ "Id": "2", "Name": "Greg", "ranges": [ { "age": "70" } ] },
{ "Id": "1", "Name": "Tom", "ranges": [ { "age": "10" } ] }
]
};
var newJson = {
"data": [
{ "Id": "2", "Name": "Greg", "ranges": [ { "age": "20" } ] },
{ "Id": "3", "Name": "Bob", "ranges": [ { "age": "30" } ] },
{ "Id": "1", "Name": "Tom", "ranges": [ { "age": "10" } ] }
]
};
function compare(newJson, oldJson) {
// get Id's from oldJson
let ids = oldJson.data.map(ch => ch.Id);
// filter from newJson that's not inside from old ids
return newJson.data.filter(ch => !ids.includes(ch.Id));
}
console.log(compare(newJson, oldJson)); // [ { Id: '3', Name: 'Bob', ranges: [ [Object] ] } ]
Upvotes: 2