Javascript 如何比较忽略数组属性中元素顺序的两个JSON?
我需要比较两个表示json对象的字符串。出于测试目的,我需要一种方法来比较这些字符串,不仅忽略子元素顺序(这很常见),而且忽略JSON数组属性中元素的顺序。即:Javascript 如何比较忽略数组属性中元素顺序的两个JSON?,javascript,json,compare,equals,jsonassert,Javascript,Json,Compare,Equals,Jsonassert,我需要比较两个表示json对象的字符串。出于测试目的,我需要一种方法来比较这些字符串,不仅忽略子元素顺序(这很常见),而且忽略JSON数组属性中元素的顺序。即: group: { id: 123, users: [ {id: 234, name: John}, {id: 345, name: Mike} ] } 应等于: group: { id: 123, users: [ {id: 345, name: Mik
group: {
id: 123,
users: [
{id: 234, name: John},
{id: 345, name: Mike}
]
}
应等于:
group: {
id: 123,
users: [
{id: 345, name: Mike},
{id: 234, name: John}
]
}
理想情况下,我需要一些javascript库,但也欢迎其他方法。我不知道是否存在这样的东西,但您可以自己实现它
var group1 = {
id: 123,
users: [
{id: 234, name: "John"},
{id: 345, name: "Mike"}
]
};
var group2 = {
id: 123,
users: [
{id: 345, name: "Mike"},
{id: 234, name: "John"}
]
};
function equal(a, b) {
if (typeof a !== typeof b) return false;
if (a.constructor !== b.constructor) return false;
if (a instanceof Array)
{
return arrayEqual(a, b);
}
if(typeof a === "object")
{
return objectEqual(a, b);
}
return a === b;
}
function objectEqual(a, b) {
for (var x in a)
{
if (a.hasOwnProperty(x))
{
if (!b.hasOwnProperty(x))
{
return false;
}
if (!equal(a[x], b[x]))
{
return false;
}
}
}
for (var x in b)
{
if (b.hasOwnProperty(x) && !a.hasOwnProperty(x))
{
return false;
}
}
return true;
}
function arrayEqual(a, b) {
if (a.length !== b.length)
{
return false;
}
var i = a.length;
while (i--)
{
var j = b.length;
var found = false;
while (!found && j--)
{
if (equal(a[i], b[j])) found = true;
}
if (!found)
{
return false;
}
}
return true;
}
alert(equal(group1, group2))
您可以对数组进行切片,按Id排序,然后将其字符串化为JSON并比较字符串。对于很多会员来说,它应该运行得相当快。如果复制ID,它将失败,因为排序不会更改顺序。使用 他们的主张不明确 松散的:
JSONAssert.assertEquals(exp, act, false);
严格的:
JSONAssert.assertEquals(exp, act, true);
以下是我对自定义实现的尝试:
var equal = (function(){
function isObject(o){
return o !== null && typeof o === 'object';
}
return function(o1, o2){
if(!isObject(o1) || !isObject(o2)) return o1 === o2;
var key, allKeys = {};
for(key in o1)
if(o1.hasOwnProperty(key))
allKeys[key] = key;
for(key in o2)
if(o2.hasOwnProperty(key))
allKeys[key] = key;
for(key in allKeys){
if(!equal(o1[key], o2[key])) return false;
}
return true;
}
})();
一个带有测试用例的示例:
var equal = (function(){
function isObject(o){
return o !== null && typeof o === 'object';
}
return function(o1, o2){
if(!isObject(o1) || !isObject(o2)) return o1 === o2;
var key, allKeys = {};
for(key in o1)
if(o1.hasOwnProperty(key))
allKeys[key] = key;
for(key in o2)
if(o2.hasOwnProperty(key))
allKeys[key] = key;
for(key in allKeys){
if(!equal(o1[key], o2[key])) return false;
}
return true;
}
})();
var p1={
标签:['1','2','3'],
姓名:'弗兰克',
年龄:24岁,
地址:{
街道:'111 E 222 W',
城市:'普罗沃',
州:“犹他州”,
邮编:84604
}
}
变量p2={
姓名:'弗兰克',
年龄:24岁,
标签:['1','2','3'],
地址:{
街道:'111 E 222 W',
城市:'普罗沃',
州:“犹他州”,
邮编:84604
}
}
变量p3={
姓名:“艾米”,
年龄:24岁,
标签:['1','2','3'],
地址:{
街道:'111 E 222 W',
城市:'普罗沃',
州:“犹他州”,
邮编:84604
}
}
变量p4={
姓名:'弗兰克',
年龄:24岁,
标签:['1','2','3'],
地址:{
街道:'111 E 222 W',
城市:“佩森”,
州:“犹他州”,
邮编:84604
}
}
变量p5={
姓名:'弗兰克',
年龄:24岁,
标签:['1','2'],
地址:{
街道:'111 E 222 W',
城市:'普罗沃',
州:“犹他州”,
邮编:84604
}
}
var equal=(函数(){
功能对象(o){
返回o!==null&&typeof o==='object';
}
返回功能(o1,o2){
如果(!isObject(o1)| |!isObject(o2))返回o1==o2;
var key,allkey={};
for(输入o1)
if(o1.hasOwnProperty(键))
所有键[键]=键;
用于(输入o2)
if(o2.hasOwnProperty(键))
所有键[键]=键;
for(输入所有键){
如果(!equal(o1[key],o2[key])返回false;
}
返回true;
}
})();
风险值案例=[
{name:'Compare with self',a:p1,b:p1,expected:true},
{name:'与相同的进行比较',a:p1,b:p2,应为:true},
{name:'Compare with different',a:p1,b:p3,应为:false},
{name:'Compare with different(nested)',a:p1,b:p4,应为:false},
{name:'与不同的(嵌套数组)进行比较',a:p1,b:p5,应为:false}
];
函数运行测试(测试){
var outEl=document.getElementById('out');
对于(变量i=0;i
正文{
字体系列:monospace;
}
.测试{
保证金:5px;
填充物:5px;
}
.通过{
背景:#EFE;
边框:实心1px#32E132;
}
.失败{
背景:#费用;
边框:实心1px#FF3232;
}
我喜欢弗朗西斯的解决方案,而且效果很好
只需在equal
函数的开头添加以下null检查,即可防止输入为null或未定义的错误
if (a == null && b == null) {
return true;
}
if (a == null || b == null) {
return false;
}
所以整个解决方案看起来像:
function equal(a, b) {
if (a == null && b == null) {
return true;
}
if (a == null || b == null) {
return false;
}
if (typeof a !== typeof b) return false;
if (a.constructor !== b.constructor) return false;
if (a instanceof Array)
{
return arrayEqual(a, b);
}
if(typeof a === "object")
{
return objectEqual(a, b);
}
return a === b;
}
function objectEqual(a, b) {
for (var x in a)
{
if (a.hasOwnProperty(x))
{
if (!b.hasOwnProperty(x))
{
return false;
}
if (!equal(a[x], b[x]))
{
return false;
}
}
}
for (var x in b)
{
if (b.hasOwnProperty(x) && !a.hasOwnProperty(x))
{
return false;
}
}
return true;
}
function arrayEqual(a, b) {
if (a.length !== b.length)
{
return false;
}
var i = a.length;
while (i--)
{
var j = b.length;
var found = false;
while (!found && j--)
{
if (equal(a[i], b[j])) found = true;
}
if (!found)
{
return false;
}
}
return true;
}
这个答案描述了使用RESTAPI解决问题的方法。DeltaJSON是一种商业产品,它将API作为服务(SaaS)或通过可在本地运行的REST服务器提供:
启动(需要Java安装和许可证文件):
java-jar deltajson-rest-1.1.0.jar
在JavaScript中,调用DeltaJSON REST API,并将arrayAlignment
属性设置为orderless
下面的示例代码显示了如何使用此属性设置调用API:
异步函数runTest(){
常量组1={
id:123,
用户:[
{id:234,姓名:“约翰”},
{id:345,名字:“迈克”}
]
};
常量组2={
id:123,
用户:[
{id:345,姓名:“Mikey”},
{id:234,姓名:“约翰”}
]
};
//进行REST API调用的调用包装器函数:
const isEqual=等待比较(第1组,第2组);
//记录比较结果:true
console.log(“isEqual”,isEqual);
}
异步函数比较(aData、bData){
const aString=JSON.stringify(aData);
const bString=JSON.stringify(bData);
constbloboptions={type:“application/json”};
var formdata=new formdata();
append(“a”,新Blob([aString],blobOptions));
append(“b”,新Blob([bString],blobOptions));
formdata.append(“arrayAlignment”、“orderless”);
const myHeaders=新的头();
附加(“接受”、“应用程序/json”);
var请求选项={
方法:“张贴”,
标题:myHeaders,
正文:formdata,
重定向:“跟随”
};
试一试{
const response=等待获取(
"http://localhost:8080/api/json/v1/compare",
请求选项
);
const jsonObj=await response.json();
console.log(jsonObj);
const dataset=jsonObj.dx_deltaJSON.dx_data_set;
常数isEqual=数据集==“A=B”;
回报均等;
}捕获(e){
控制台错误(e);
}
}
//运行测试:
runTest();//真的
说明:
DeltaJSON Rest API响应是JSON输入的注释形式。添加了额外的dx
前缀属性来描述更改。元数据dx_deltaJSON
属性也包含在JSON中
dx\u deltaJSON
属性的值是一个具有dx\u data\u set
属性的对象,我们可以测试该属性以查看(在双向比较中)该值是否为a=B
这是一个与问题中的输入略有不同的结果。他