如何比较两个没有顺序的具有相同属性的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) );
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script>
【讨论】:
【参考方案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?的主要内容,如果未能解决你的问题,请参考以下文章