简体   繁体   中英

How to compare two JSON have the same properties without order?

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 (ie libraries for comparing JSON) ?

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>

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 isEqual() method

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

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);

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

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));

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.

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

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;
}

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;
        },

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

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.

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM