如何比较两个没有顺序的具有相同属性的JSON?

Posted

技术标签:

【中文标题】如何比较两个没有顺序的具有相同属性的JSON?【英文标题】:How to compare two JSON have the same properties without order? 【发布时间】:2014-11-20 20:37:33 【问题描述】:

我尝试比较这两个 JSON 对象:

<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 />

我用 javascript 获得了值,并尝试与 JSON.stringify(remoteJSON) == JSON.stringify(localJSON) 进行比较,但这返回 false:似乎属性的顺序很重要。

我什至尝试与this solution 进行深度比较,但总是得到错误的回报。

有没有一种快速的方法来解决 jQuery 的问题(即用于比较 JSON 的库)?

【问题讨论】:

你应该阅读这个***.com/questions/171251/… 你能告诉我们你是如何尝试深度比较的吗? "总是得到一个错误的返回" --- 不,它不会 jsfiddle.net/pyLqhujo 如果该函数返回 false 它字面意思是你的对象不同的。 @zerkms: 我以前比较的是字符串而不是对象,所以现在可以返回 true 语句...+1 抱歉,这是我的错 【参考方案1】:

Lodash _.isEqual 允许你这样做:

var
remoteJSON = "allowExternalMembers": "false", "whoCanJoin": "CAN_REQUEST_TO_JOIN",
    localJSON = "whoCanJoin": "CAN_REQUEST_TO_JOIN", "allowExternalMembers": "false";
    
console.log( _.isEqual(remoteJSON, localJSON) );
&lt;script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"&gt;&lt;/script&gt;

【讨论】:

【参考方案2】:

Lodash isEqual() 方法是比较两个 JSON 对象的最佳方法。

这将不考虑对象中键的顺序并检查对象的相等性。示例

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

参考 - https://lodash.com/docs/#isEqual

如果序列不会改变,JSON.stringify() 将比 Lodash 的 isEqual() 方法快。

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

【讨论】:

【参考方案3】:

在 javascript 中比较两个 json 字符串的简单方法

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

【讨论】:

这适用于原始值。如果 obj[key]obj2[key 有嵌套对象,那么这将失败,因为对象是通过它们的引用进行比较的。【参考方案4】:

DeepCompare 方法比较两个 json 对象..

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

【讨论】:

【参考方案5】:

此代码将独立于参数对象顺序验证 json。

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

【讨论】:

【参考方案6】:

我改编并修改了this tutorial 的代码,以编写一个对两个 JS 对象进行深度比较的函数。

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

该函数比较两个对象的相同键的各自值。此外,如果这两个值是对象,它也会使用递归对它们执行深度比较。

希望这会有所帮助。

【讨论】:

【参考方案7】:

lodash 可以工作,即使是 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
    

它可以工作,要以角度安装,请关注this

【讨论】:

【参考方案8】:

这个问题提醒了如何确定两个 JavaScript 对象相等。 所以,我会选择this通用函数

比较 JS 对象:

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;

【讨论】:

所以,基本上你只是复制了this answer? @Ja͢ck:或者他们误判了。 @BoltClock 即使是这样,这也不能回答问题,因为问题不在于使用的比较函数。 @Ja͢ck:是的。抱歉,我并没有试图为这个答案辩护——无论是抄袭还是错误归因都不会改变任何事情。不过还是等作者修复吧。 (不过,这是一个善意的尝试来回答这个问题,因此不属于 NAA。) @BoltClock 不用担心,这篇文章可能已被标记,乍一看,错误归因似乎是最合乎逻辑的问题:)【参考方案9】:

在 VueJs 函数中,您也可以使用它...使用递归的可行解决方案。基本学分 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;
        ,

【讨论】:

【参考方案10】:

我们使用node-deep-equal 项目,它实现了与nodejs 相同的深度相等比较

google serach for deep-equal on npm 会告诉你很多选择

【讨论】:

【参考方案11】:

如果您尝试比较这两个对象与我的目标相同:即仅反序列化一个有效对象,在这种情况下,我建议您使用以下方法:

using Newtonsoft.Json;

try

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

    
    throw;

如果捕获到错误,那么您的对象不属于 YourTargetObjectType。否则很好,你可以对第二个对象做同样的事情。

带有 MissingMemberHandling 的 JsonSerializerSetings 可以解决问题。在 mme 异常对象中,您可以检查哪个属性属性失败。这会验证额外的属性、缺失的属性和/或拼写错误的属性。

因此,在您的情况下,您应该有一个 Object 用作​​比较两个对象的参考。

【讨论】:

【参考方案12】:

由于@zerkems 评论:

我应该将我的字符串转换为 JSON 对象,然后调用 equal 方法:

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;

【讨论】:

不要使用eval();有JSON.parse()$.parseJSON()

以上是关于如何比较两个没有顺序的具有相同属性的JSON?的主要内容,如果未能解决你的问题,请参考以下文章

将 pandas 数据框导出到 json 并返回到具有相同顺序的列的数据框

如何以任何顺序比较两个 NSArray 的相同内容?

当条目的顺序不断变化时如何比较两个JSON字符串[重复]

JS sort() 按照某个属性对数组进行排序

比较链表,C++,相同的顺序但可以不同的抓住

当两个 jar 具有相同的类集时,使用 jboss/wildfly 的类加载冲突,如何设置顺序/优先级?