2011-11-11 14 views
3

jsonオブジェクトを表す2つの文字列を比較する必要があります。テスト目的のために、私はこれらの文字列を比較する方法を必要とするだけでなく、子要素の順序(かなり共通)がjsonsの配列プロパティの要素の順序を無視します。すなわち:配列プロパティの要素の順序を無視する2つの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

配列をスライスし、IDでソートし、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の元の例です。:) 問題は、実装では基本的に配列をセットとして扱うことです。 –

関連する問題