11

json オブジェクトを表す 2 つの文字列を比較する必要があります。テスト目的で、子要素の順序 (非常に一般的) だけでなく、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 ライブラリが必要ですが、他のアプローチも歓迎します。

4

6 に答える 6

13

JSONAssertを使用する

彼らは緩いアサートを持っています。

ゆるい:

JSONAssert.assertEquals(exp, act, false);

厳しい:

JSONAssert.assertEquals(exp, act, true);
于 2015-05-06T22:45:47.163 に答える
2

そのようなものが存在するかどうかはわかりませんが、自分で実装できます。

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))
于 2011-11-11T20:01:06.737 に答える
1

配列をスライスし、ID で並べ替えてから JSON に文字列化し、文字列を比較できます。多くのメンバーにとって、それはかなり速く動作するはずです。Id を複製すると、並べ替えによって順序が変更されないため、失敗します。

于 2011-11-11T20:16:35.923 に答える
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>

于 2015-11-19T20:54:04.013 に答える