Yuval
Yuval

Reputation: 15

JavaScript compare two JSON files and outputting new objects only

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

Answers (2)

Jorge Takeshi Sato
Jorge Takeshi Sato

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

halilcakar
halilcakar

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

Related Questions