Search code examples
javascriptjsonangulartypescriptobject

Compare Nested Objects and save difference in new object using Javascript


I have two Javascript objects

var order1 = {
    sandwich: 'tuna',
    chips: true,
    drink: 'soda',
    order: 1,
    toppings: [{VendorNumber: 18, PreferredFlag: false, SupportedFlag: true}, {VendorNumber: 19, PreferredFlag: false, SupportedFlag: true}, {VendorNumber: 20, PreferredFlag: false, SupportedFlag: true}],
    details: {
        name: 'Chris',
        phone: '555-555-5555',
        email: '[email protected]'
    },
    otherVal1: '1'
};

var order2 = {
    sandwich: 'turkey',
    chips: true,
    drink: 'soda',
    order: 2,
    toppings: [{VendorNumber: 18, PreferredFlag: false, SupportedFlag: true}, {VendorNumber: 19, PreferredFlag: false, SupportedFlag: false}, {VendorNumber: 20, PreferredFlag: true, SupportedFlag: true}],
    details: {
        name: 'Jon',
        phone: '(555) 555-5555',
        email: '[email protected]'
    },
    otherVal1: '2'
};

What I need is to compare these two objects (order1 is existing and order2 is the edited data) and store the difference in a new variable named var order3. However if there is an array inside an object like the toppings array to be copied as whole with the changes.

In short the result should be

{
  details: {
    email: "[email protected]",
    name: "Jon",
    phone: "(555) 555-5555"
  },
  order: 2,
  otherVal1: "2",
  sandwich: "turkey",
  toppings: [{
  PreferredFlag: false,
  SupportedFlag: true,
  VendorNumber: 18
}, {
  PreferredFlag: false,
  SupportedFlag: false,
  VendorNumber: 19
}, {
  PreferredFlag: true,
  SupportedFlag: true,
  VendorNumber: 20
}]
}

How can i achieve this ?


Solution

  • This gives you exactly what you wanted:

    function diff(tgt, src) {
    
        if (Array.isArray(tgt)) { // if you got array
            return tgt; // just copy it
        }
    
        // if you got object
        var rst = {};
        for (var k in tgt) { // visit all fields
            if (typeof src[k] === "object") { // if field contains object (or array because arrays are objects too)
                rst[k] = diff(tgt[k], src[k]); // diff the contents
            } else if (src[k] !== tgt[k]) { // if field is not an object and has changed
                rst[k] = tgt[k]; // use new value
            }
            // otherwise just skip it
        }
        return rst;
    }
    console.log(diff(order2, order1));