Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/442.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何比较忽略数组属性中元素顺序的两个JSON?_Javascript_Json_Compare_Equals_Jsonassert - Fatal编程技术网

Javascript 如何比较忽略数组属性中元素顺序的两个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

我需要比较两个表示json对象的字符串。出于测试目的,我需要一种方法来比较这些字符串,不仅忽略子元素顺序(这很常见),而且忽略JSON数组属性中元素的顺序。即:

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

    这是一个与问题中的输入略有不同的结果。他