60

I have tried to compare those two JSON objects:

<input type="hidden" id="remoteJSON" name="remoteJSON" value='{"allowExternalMembers": "false", "whoCanJoin": "CAN_REQUEST_TO_JOIN"}' /><br />
<input type="hidden" id="localJSON" name="localJSON" value='{"whoCanJoin": "CAN_REQUEST_TO_JOIN", "allowExternalMembers": "false"}' /><br />

I got values with javascript and I tried to compare with : JSON.stringify(remoteJSON) == JSON.stringify(localJSON) but this return false: it seems that the order of the properties is important.

And I even tried deep compare with this solution and always got a false return.

Is there a fast way to do the issue with jQuery (i.e. libraries for comparing JSON) ?

M Y K
  • 5
  • 3
Drwhite
  • 1,545
  • 4
  • 21
  • 44

16 Answers16

48

Lodash _.isEqual allows you to do that:

var
remoteJSON = {"allowExternalMembers": "false", "whoCanJoin": "CAN_REQUEST_TO_JOIN"},
    localJSON = {"whoCanJoin": "CAN_REQUEST_TO_JOIN", "allowExternalMembers": "false"};
    
console.log( _.isEqual(remoteJSON, localJSON) );
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script>
Adam Azad
  • 11,171
  • 5
  • 29
  • 70
Nicolas
  • 743
  • 1
  • 7
  • 15
28

Lodash isEqual() method is the best way to compare two JSON object.

This will not consider the order of the keys in object and check for the equality of object. Example

const object1 = {
  name: 'ABC',
  address: 'India'
};
    
const object2 = {
  address: 'India',
  name: 'ABC'
};
    
JSON.stringify(object1) === JSON.stringify(object2)
// false
    
_.isEqual(object1, object2)
// true

Reference - https://lodash.com/docs/#isEqual

If sequence is not going to change than JSON.stringify() will be fast as compared to Lodash's isEqual() method.

Reference - https://www.measurethat.net/Benchmarks/Show/1854/0/lodash-isequal-test

romellem
  • 5,792
  • 1
  • 32
  • 64
Ashita.gupta
  • 321
  • 3
  • 5
  • It is bad solution since it not works if the objects keys order are mixed and not sorted. – IGHOR May 23 '22 at 01:29
10

DeepCompare method to compare two json objects..

deepCompare = (arg1, arg2) => {
  if (Object.prototype.toString.call(arg1) === Object.prototype.toString.call(arg2)){
    if (Object.prototype.toString.call(arg1) === '[object Object]' || Object.prototype.toString.call(arg1) === '[object Array]' ){
      if (Object.keys(arg1).length !== Object.keys(arg2).length ){
        return false;
      }
      return (Object.keys(arg1).every(function(key){
        return deepCompare(arg1[key],arg2[key]);
      }));
    }
    return (arg1===arg2);
  }
  return false;
}

console.log(deepCompare({a:1},{a:'1'})) // false
console.log(deepCompare({a:1},{a:1}))   // true
ajit-jain
  • 206
  • 2
  • 6
3

Easy way to compare two json string in javascript

var obj1 = {"name":"Sam","class":"MCA"};
var obj2 = {"class":"MCA","name":"Sam"};

var flag=true;

if(Object.keys(obj1).length==Object.keys(obj2).length){
    for(key in obj1) { 
        if(obj1[key] == obj2[key]) {
            continue;
        }
        else {
            flag=false;
            break;
        }
    }
}
else {
    flag=false;
}
console.log("is object equal"+flag);
  • 4
    This will work for primitive values. If `obj[key]` and `obj2[key` have nested objects then this will fail because objects are compared by their reference. – The Witness Jul 15 '19 at 12:18
3

I adapted and modified the code from this tutorial to write a function that does a deep comparison of two JS objects.

const isEqual = function(obj1, obj2) {
    const obj1Keys = Object.keys(obj1);
    const obj2Keys = Object.keys(obj2);

    if(obj1Keys.length !== obj2Keys.length) {
        return false;
    }

    for (let objKey of obj1Keys) {
        if (obj1[objKey] !== obj2[objKey]) {
            if(typeof obj1[objKey] == "object" && typeof obj2[objKey] == "object") {
                if(!isEqual(obj1[objKey], obj2[objKey])) {
                    return false;
                }
            } 
            else {
                return false;
            }
        }
    }

    return true;
};

The function compares the respective values of the same keys for the two objects. Further, if the two values are objects, it uses recursion to execute deep comparison on them as well.

Hope this helps.

Amjad Abujamous
  • 736
  • 9
  • 9
3

This code will verify the json independently of param object order.

var isEqualsJson = (obj1,obj2)=>{
    keys1 = Object.keys(obj1);
    keys2 = Object.keys(obj2);

    //return true when the two json has same length and all the properties has same value key by key
    return keys1.length === keys2.length && Object.keys(obj1).every(key=>obj1[key]==obj2[key]);
}

var obj1 = {a:1,b:2,c:3};
var obj2 = {a:1,b:2,c:3}; 

console.log("json is equals: "+ isEqualsJson(obj1,obj2));
alert("json is equals: "+ isEqualsJson(obj1,obj2));
1

lodash will work, tested even for angular 5, http://jsfiddle.net/L5qrfx3x/

var remoteJSON = {"allowExternalMembers": "false", "whoCanJoin": 
   "CAN_REQUEST_TO_JOIN"};
var localJSON = {"whoCanJoin": "CAN_REQUEST_TO_JOIN", 
  "allowExternalMembers": "false"};

 if(_.isEqual(remoteJSON, localJSON)){
     //TODO
    }

it works, for installation in angular, follow this

Thomas John
  • 2,138
  • 2
  • 22
  • 38
1

This function works for objects with simple primitives:

function compareObjects(o1, o2) {
  const normalizedObj1 = Object.fromEntries(Object.entries(o1).sort(([k1], [k2]) => k1. localeCompare(k2)));
  const normalizedObj2 = Object.fromEntries(Object.entries(o2).sort(([k1], [k2]) => k1. localeCompare(k2)));
  return JSON.stringify(normalizedObj1) === JSON.stringify(normalizedObj2);
}

compareObjects({a: 1, b: 2}, {b: 2, a: 1}); // true

If the objects contain nested objects, it won't work because we need to normalize them recursively

Arik
  • 5,266
  • 1
  • 27
  • 26
1

Note: This implementation only works for JSON objects that do not contain circular references. If your JSON objects may contain circular references, you will need to modify the implementation accordingly.

function deepCompare(obj1, obj2) {
  // compare types
  if (typeof obj1 !== typeof obj2) {
    return false;
  }

  // compare properties recursively
  if (typeof obj1 === 'object') {
    if (Array.isArray(obj1) !== Array.isArray(obj2)) {
      return false;
    }
    if (Array.isArray(obj1)) {
      if (obj1.length !== obj2.length) {
        return false;
      }
      for (let i = 0; i < obj1.length; i++) {
        if (!deepCompare(obj1[i], obj2[i])) {
          return false;
        }
      }
    } else {
      const keys1 = Object.keys(obj1);
      const keys2 = Object.keys(obj2);
      if (keys1.length !== keys2.length) {
        return false;
      }
      for (const key of keys1) {
        if (
          !Object.prototype.hasOwnProperty.call(obj2, key) ||
          !deepCompare(obj1[key], obj2[key])
        ) {
          return false;
        }
      }
    }
  } else {
    // compare primitive values
    if (obj1 !== obj2) {
      return false;
    }
  }

  // objects are equal
  return true;
}


const json1 = '{"name": "John", "age": 30, "address": {"street": "123 Main St", "city": "Anytown"}}';
const json2 = '{"name": "John", "age": 30, "address": {"street": "123 Main St", "city": "Anytown"}}';

const obj1 = JSON.parse(json1);
const obj2 = JSON.parse(json2);

console.log(deepCompare(obj1, obj2));
Syed
  • 15,657
  • 13
  • 120
  • 154
0

This question reminds of how to determine equality for two JavaScript objects. So, I would choose this general function

Compares JS objects:

function objectEquals(x, y) {
    // if both are function
    if (x instanceof Function) {
        if (y instanceof Function) {
            return x.toString() === y.toString();
        }
        return false;
    }
    if (x === null || x === undefined || y === null || y === undefined) { return x === y; }
    if (x === y || x.valueOf() === y.valueOf()) { return true; }

    // if one of them is date, they must had equal valueOf
    if (x instanceof Date) { return false; }
    if (y instanceof Date) { return false; }

    // if they are not function or strictly equal, they both need to be Objects
    if (!(x instanceof Object)) { return false; }
    if (!(y instanceof Object)) { return false; }

    var p = Object.keys(x);
    return Object.keys(y).every(function (i) { return p.indexOf(i) !== -1; }) ?
            p.every(function (i) { return objectEquals(x[i], y[i]); }) : false;
}
Community
  • 1
  • 1
Giannis Grivas
  • 3,374
  • 1
  • 18
  • 38
  • 7
    So, basically you've just copied [this answer](http://stackoverflow.com/a/16788517/1338292)? – Ja͢ck Sep 25 '14 at 23:14
  • 1
    @Ja͢ck: Or they misattributed. – BoltClock Sep 26 '14 at 00:11
  • @BoltClock Even if that were the case, this doesn't answer the question because the problem was not in the comparison function that was used. – Ja͢ck Sep 26 '14 at 00:13
  • @Ja͢ck: Yeah. Sorry I wasn't trying to defend this answer - whether it was plagiarized or misattributed doesn't change anything. But I'll wait for the author to fix it up. (It is a good-faith attempt to answer the question though, and so does not fall under NAA.) – BoltClock Sep 26 '14 at 00:17
  • @BoltClock No worries, this post was probably flagged and at first sight the misattribution seems the most logical issue :) – Ja͢ck Sep 26 '14 at 00:22
0

In VueJs function you can use this as well... A working solution using recursion. Base credits Samadhan Sakhale

     check_objects(obj1, obj2) {
            try {
                var flag = true;

                if (Object.keys(obj1).length == Object.keys(obj2).length) {
                    for (let key in obj1) {

                        if(typeof (obj1[key]) != typeof (obj2[key]))
                        {
                            return false;
                        }

                        if (obj1[key] == obj2[key]) {
                            continue;
                        }

                        else if(typeof (obj1[key]) == typeof (new Object()))
                        {
                            if(!this.check_objects(obj1[key], obj2[key])) {
                                return false;
                            }
                        }
                        else {
                            return false;
                        }
                    }
                }
                else {
                    return false
                }
            }
            catch {

                return false;
            }

            return flag;
        },
Hassan Alvi
  • 315
  • 2
  • 10
0

We use the node-deep-equal project which implements the same deep-equal comparison as nodejs

A google serach for deep-equal on npm will show you many alternatives

TmTron
  • 17,012
  • 10
  • 94
  • 142
0

If you are trying to compare those two objects with the same goal as mine: which is to deserialize just an valid object, in that case, I would recommend you to use the following method:

using Newtonsoft.Json;

try
{
    var myObj = JsonConvert.DeserializeObject<**YourTargetObjectType**>(jsonString, new JsonSerializerSettings
    {
        MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
        MissingMemberHandling = MissingMemberHandling.Error
    });
}catch (MissingMemberException mme)
{
    
    throw;
}

If an error get caught, so your object does not belong to YourTargetObjectType. Otherwise it is good to go, and you can do the same for the second object.

The JsonSerializerSetings with the MissingMemberHandling do the trick. And in the mme exception object you can check which property property failed. This validates extra properties, missing ones and/or misspelled properties.

So in your case, you should have a Object which will be used as reference to compare both objects.

Ricardo Coelho
  • 448
  • 4
  • 7
0

There is Intellij Idea plugin for this purpose: https://plugins.jetbrains.com/plugin/20169-json-comparator?preview=true It sorts all fields and objects in arrays recursively

Volodymyr Kret
  • 1,511
  • 15
  • 16
0

with JSONata simply use = operator

async function compare() {
  const jsonEQObj = {
    object1: {
      name: 'ABC',
      address: 'India'
    },
    object2: {
      address: 'India',
      name: 'ABC'
    }
  };
  let isEqual = await jsonata('object1=object2').evaluate(jsonEQObj)
  console.log(isEqual)

  jsonEQObj.object1.name = 'X';
  isEqual = await jsonata('object1=object2').evaluate(jsonEQObj)
  console.log(isEqual)
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>JSONata test</title>
  <script src="https://cdn.jsdelivr.net/npm/jsonata/jsonata.min.js"></script>
</head>

<body onload=compare()>
</body>

</html>
perimeno
  • 177
  • 1
  • 8
-1

Due to @zerkems comment:

i should convert my strings to JSON object and then call the equal method:

var x = eval("(" + remoteJSON + ')');
var y = eval("(" + localJSON + ')');

function jsonequals(x, y) {
    // If both x and y are null or undefined and exactly the same
    if ( x === y ) {
        return true;
    }

    // If they are not strictly equal, they both need to be Objects
    if ( ! ( x instanceof Object ) || ! ( y instanceof Object ) ) {
        return false;
    }

    // They must have the exact same prototype chain, the closest we can do is
    // test the constructor.
    if ( x.constructor !== y.constructor ) {
        return false;
    }

    for ( var p in x ) {
        // Inherited properties were tested using x.constructor === y.constructor
        if ( x.hasOwnProperty( p ) ) {
            // Allows comparing x[ p ] and y[ p ] when set to undefined
            if ( ! y.hasOwnProperty( p ) ) {
                return false;
            }

            // If they have the same strict value or identity then they are equal
            if ( x[ p ] === y[ p ] ) {
                continue;
            }

            // Numbers, Strings, Functions, Booleans must be strictly equal
            if ( typeof( x[ p ] ) !== "object" ) {
                return false;
            }

            // Objects and Arrays must be tested recursively
            if ( !equals( x[ p ],  y[ p ] ) ) {
                return false;
            }
        }
    }

    for ( p in y ) {
        // allows x[ p ] to be set to undefined
        if ( y.hasOwnProperty( p ) && ! x.hasOwnProperty( p ) ) {
            return false;
        }
    }
    return true;
}
Drwhite
  • 1,545
  • 4
  • 21
  • 44