2011-11-11 56 views
3

我需要比较两个代表json对象的字符串。为了测试目的,我需要一种方法来比较这些字符串,不仅忽略子元素顺序(这很常见),而且还会忽略jsons的数组属性中元素的顺序。即:如何比较两个jsons忽略数组属性的顺序?

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的lib,但其他方法也表示欢迎。

+1

也许这人会帮助? http://stackoverflow.com/questions/4465244/compare-2-json-objects – hummingBird

回答

0

我不知道这样的东西是否存在,但你可以自己实现它。

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

你可以切片的阵列,通过标识进行排序,然后他们对字符串化JSON和比较字符串。对于很多成员来说,它应该工作得很快。如果您复制ID,则它将失败,因为排序不会更改订单。

2

使用JSONAssert

他们有一个宽松的断言。

宽松:

JSONAssert.assertEquals(exp, act, false); 

严格:

JSONAssert.assertEquals(exp, act, true); 
+0

这看起来像一个Java解决方案,但OP用JavaScript标记了这个问题。 – Trevor

+0

“但其他方法也欢迎”这是另一种方法:) – kecso

+0

Touche。你有我。 – Trevor

0

这是我在一个自定义实现尝试:

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 = { 
 
    tags: ['one', 'two', 'three'], 
 
    name: 'Frank', 
 
    age: 24, 
 
    address: { 
 
    street: '111 E 222 W', 
 
    city: 'Provo', 
 
    state: 'Utah', 
 
    zip: '84604' 
 
    } 
 
} 
 
var p2 = { 
 
    name: 'Frank', 
 
    age: 24, 
 
    tags: ['one', 'two', 'three'], 
 
    address: { 
 
    street: '111 E 222 W', 
 
    city: 'Provo', 
 
    state: 'Utah', 
 
    zip: '84604' 
 
    } 
 
} 
 
var p3 = { 
 
    name: 'Amy', 
 
    age: 24, 
 
    tags: ['one', 'two', 'three'], 
 
    address: { 
 
    street: '111 E 222 W', 
 
    city: 'Provo', 
 
    state: 'Utah', 
 
    zip: '84604' 
 
    } 
 
} 
 
var p4 = { 
 
    name: 'Frank', 
 
    age: 24, 
 
    tags: ['one', 'two', 'three'], 
 
    address: { 
 
    street: '111 E 222 W', 
 
    city: 'Payson', 
 
    state: 'Utah', 
 
    zip: '84604' 
 
    } 
 
} 
 
var p5 = { 
 
    name: 'Frank', 
 
    age: 24, 
 
    tags: ['one', 'two'], 
 
    address: { 
 
    street: '111 E 222 W', 
 
    city: 'Provo', 
 
    state: 'Utah', 
 
    zip: '84604' 
 
    } 
 
} 
 

 
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 cases = [ 
 
    {name: 'Compare with self', a: p1, b: p1, expected: true}, 
 
    {name: 'Compare with identical', a: p1, b: p2, expected: true}, 
 
    {name: 'Compare with different', a: p1, b: p3, expected: false}, 
 
    {name: 'Compare with different (nested)', a: p1, b: p4, expected: false}, 
 
    {name: 'Compare with different (nested array)', a: p1, b: p5, expected: false} 
 
]; 
 

 
function runTests(tests){ 
 
    var outEl = document.getElementById('out'); 
 
    for(var i=0; i < tests.length; i++){ 
 
    var actual = equal(tests[i].a, tests[i].b), 
 
     result = tests[i].expected == actual 
 
      ? 'PASS' 
 
      : 'FAIL'; 
 
    outEl.innerHTML += 
 
     '<div class="test ' + result + '">' + 
 
     result + ' ' + 
 
     tests[i].name + 
 
     '</div>'; 
 
    } 
 
} 
 
runTests(cases);
body{ 
 
    font-family:monospace; 
 
} 
 
.test{ 
 
    margin:5px; 
 
    padding:5px; 
 
} 
 
.PASS{ 
 
    background:#EFE; 
 
    border:solid 1px #32E132; 
 
} 
 
.FAIL{ 
 
    background:#FEE; 
 
    border:solid 1px #FF3232; 
 
}
<div id=out></div>

+0

如果有人发现一个不适用于此解决方案的边缘案例,我将不胜感激。 – Trevor

+0

那么,OP的原始示例,一件事:) 问题是,实现应该基本上将数组视为集。 –

相关问题