jQuery/JavaScript JSON 对象比较

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8108666/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 02:18:57  来源:igfitidea点击:

jQuery/JavaScript JSON object comparison

javascriptjqueryjson

提问by chris

Is it possible to compare 2 sets of json objects for a difference? What I have is a script thats polling for JSON object via jquery $post(). What I want to do is take the object that was just polled and compare it to a stored one. Where if there is any changes from one to the other apply them to the stored object or replace it (either way) but from the UI perspective I am working with seamlessly apply the changes to what the JSON object is for by finding the differences between the 2. I want to do this because right now I have it so the UI is completely reloading per poll regardless of change or not which basically looks like ** from a UX perspective.

是否可以比较 2 组 json 对象的差异?我有一个脚本,它通过 jquery $post() 轮询 JSON 对象。我想要做的是获取刚刚轮询的对象并将其与存储的对象进行比较。如果从一个到另一个有任何更改,请将它们应用于存储的对象或替换它(无论哪种方式),但从 UI 的角度来看,我正在使用通过查找 JSON 对象之间的差异无缝地将更改应用于 JSON 对象的用途2. 我想这样做是因为现在我拥有它,因此无论是否发生变化,UI 都会完全重新加载每次轮询,从 UX 的角度来看,这基本上看起来像**。

I figure if I can find the differences if any between the 2 objects I would fire off a function that I would have edit the UI specific to the differences.

我想如果我能找到两个对象之间的差异,我会触发一个功能,我将编辑特定于差异的 UI。

回答by nnnnnn

What I want to do is take the object that was just polled and compare it to a stored one. Where if there is any changes from one to the other apply them to the stored object or replace it (either way)

我想要做的是获取刚刚轮询的对象并将其与存储的对象进行比较。如果从一个到另一个有任何更改,请将它们应用于存储的对象或替换它(无论哪种方式)

If you would be happy with a really simple "Has it changed in any way? Yes/No" solution, where if it has changed you just replace the previous object with the new one (as per the part of your question that I quoted), then you could save the JSON response beforeyou parse it, i.e., save it in the stringformat in which your web-server sends it. Then when the next response comes in compare the new string with the old string. If they are different (or if it is the first request) parse the JSON and process it for display as appropriate. Naturally this assumes that your server-side code is creating the JSON strings in a consistent format (and not, e.g., changing the order of the properties).

如果您对一个非常简单的“它以任何方式改变了吗?是/否”的解决方案感到满意,如果它改变了,您只需用新对象替换以前的对象(根据我引用的问题部分) ,那么您可以解析它之前保存 JSON 响应,即,将其保存为您的网络服务器发送它的字符串格式。然后当下一个响应到来时,将新字符串与旧字符串进行比较。如果它们不同(或者如果它是第一个请求)解析 JSON 并处理它以进行适当的显示。当然,这假设您的服务器端代码以一致的格式创建 JSON 字符串(而不是,例如,更改属性的顺序)。

If we assume you've already got (parsed) objects, an isEqual(a,b)function really should cope with nested objects, properties that are arrays, etc. This can be done recursively, and simply return true or false, but a getDifferences(a,b)function is going to get confusing in how it reports the differences within nested objects. Consider this simple example:

如果我们假设您已经获得(解析)对象,那么isEqual(a,b)函数真的应该处理嵌套对象、数组属性等。这可以递归完成,只需返回 true 或 false,但getDifferences(a,b)函数会变得混乱它如何报告嵌套对象内的差异。考虑这个简单的例子:

old: {"mum" : "Maria", "dad" : "Pierre", "kids" : ["Joe", "Mike", "Louisa"] }
new: {"mum" : "Julie", "dad" : "Pierre", "kids" : ["Joe", "Mary"] }

Is the difference {"mum" : "Julie", "kids" : ["Mary"]}? The "mum" has changed, and the list of "kids" has changed, but has "Mike" changed to "Mary", or are both "Mike" and "Louisa" gone with "Mary" being new, or...? Maybe it should be "kids": ["Joe","Mary"]because that's the new value. How do you indicate the deletions? That's just the first example off the top of my head where I don't know how you would want to handle the differences. It could quickly get worse: what if the "kids" array contained objects instead of strings to represent a whole family tree? What if the new "mum" property was ["Maria", "Julie"](to allow for step-parents and so forth)?

有区别{"mum" : "Julie", "kids" : ["Mary"]}吗?“妈妈”变了,“孩子”的名单也变了,但是“迈克”变成了“玛丽”,或者“迈克”和“路易莎”都消失了,而“玛丽”是新的,或者…… ? 也许应该是"kids": ["Joe","Mary"]因为那是新值。你如何表示删除?这只是我头顶上的第一个例子,我不知道你想如何处理这些差异。它可能很快变得更糟:如果“kids”数组包含对象而不是字符串来表示整个家谱呢?如果新的“妈妈”财产是["Maria", "Julie"](允许继父母等)怎么办?

If for your particular data you know you've only got one-dimensional objects then you can do something simple like the following:

如果对于您的特定数据,您知道您只有一维对象,那么您可以执行以下简单操作:

function getDifferences(oldObj, newObj) {
   var diff = {};

   for (var k in oldObj) {
      if (!(k in newObj))
         diff[k] = undefined;  // property gone so explicitly set it undefined
      else if (oldObj[k] !== newObj[k])
         diff[k] = newObj[k];  // property in both but has changed
   }

   for (k in newObj) {
      if (!(k in oldObj))
         diff[k] = newObj[k]; // property is new
   }

   return diff;
}

The simplest change to the above to allow for nested objects is to just assume that if a property is an object/array then you only care whether it is different in any way and not dig down to report exactly which "sub-properties" have changed. If so, simply take the above function and change:

对上面允许嵌套对象的最简单的更改是假设如果一个属性是一个对象/数组,那么您只关心它是否有任何不同,而不是深入报告究竟哪些“子属性”发生了变化. 如果是这样,只需采用上述功能并更改:

else if (oldObj[k] !== newObj[k])

to

else if (!isEqual(oldObj[k],newObj[k]))

Where isEqual()is one of the many comparison functions floating around the web or on StackOverflow.

isEqual()网上或StackOverflow上的众多比较函数之一在哪里。

(Note: I haven't bothered with .hasOwnProperty()above because I assume that objects that were returned to an Ajax request as JSON will not be inheriting properties from a prototype chain. Similarly an isEqual()function for this purpose wouldn't need to worry about properties being functions, it only needs to worry about what is valid in a JSON string.)

(注意:我没有在意.hasOwnProperty()上面的内容,因为我假设作为 JSON 返回到 Ajax 请求的对象不会从原型链继承属性。类似地,isEqual()用于此目的的函数不需要担心属性是函数,它只需要关心 JSON 字符串中什么是有效的。)

回答by Mou

Sorry to answer old thread but my answer may help others who may face the same issue.the most easiest & shortest code to compare two json object as follows. thanks

很抱歉回答旧线程,但我的回答可能会帮助其他可能面临相同问题的人。比较两个 json 对象的最简单和最短的代码如下。谢谢

<script type="text/javascript">
    $(document).ready(function () {
        var a = { "id": "210", "memberlist": "john" };
        var b = { "id": "210", "memberlist": "john1" };

        alert(JSON.stringify(a) != JSON.stringify(b) ? 'not same' : ' same');
    });
</script>

回答by Jonathan Arias

Here is my code:

这是我的代码:

    function getDifferences(oldObj, newObj) {
    var diff = {};

    for (var k in oldObj) {
        if (!(k in newObj)){
            diff[k] = undefined;  // old key does not exist in new
        } else {
            switch (typeof oldObj[k]){
                case "array": {
                    String(oldObj[k]) !== String(newObj[k]) ? diff[k] = newObj[k] : null;
                    break;
                } case "object": {                        
                    Object.keys(oldObj[k]).forEach(key =>{                           
                        if(oldObj[k][key] !== newObj[k][key]){
                            if(diff[k]){
                                diff[k][key] = newObj[k][key];
                            } else {
                                diff[k] = {[key]: newObj[k][key]}
                            }
                        }
                    });
                    //JSON.stringify(oldObj[k]) !== JSON.stringify(newObj[k]) ? diff[k] = newObj[k] : null; Optional basic comparision
                    break;
                } default: { //Values are strings or numbers
                    oldObj[k] !== newObj[k] ? diff[k] = newObj[k] : null;
                    break;
                }
            }
        }
    }

    for (k in newObj) {
        if (!(k in oldObj))
        diff[k] = newObj[k]; // property is new
    }     
    return diff;
}

We get the type of the elements and make an internal comparision of equality.

我们获取元素的类型并进行内部相等性比较。

回答by bstakes

One potential solution could be to use jQuery's extend. As long as the objects have the same properties, that would work out nicely.

一种潜在的解决方案可能是使用 jQuery 的扩展。只要对象具有相同的属性,就会很好地解决问题。

var newJSON = $.extend({},oldJSON,serverData);

Then you would have preserved the old object, and created a new object with any properties from the old object if they aren't present in the new object and overwritten any existing properties with the properties from the new data from the server.

然后,您将保留旧对象,并使用旧对象中的任何属性创建一个新对象(如果新对象中不存在这些属性),并使用来自服务器的新数据中的属性覆盖任何现有属性。

回答by morgancodes

var objectsAreEqual = function(obj1, x){
  var MAX_DEPTH = 10;
  var testEq = function(obj1, x, depth){
    if(depth < MAX_DEPTH){
      for (var p in obj1) {
          if(typeof(obj1[p]) !== typeof(x[p])) return false;
          if((obj1[p]===null) !== (x[p]===null)) return false;
          switch (typeof(obj1[p])) {
              case 'undefined':
                  if (typeof(x[p]) != 'undefined') return false;
                  break;
              case 'object':
                  if(obj1[p]!==null && x[p]!==null && (obj1[p].constructor.toString() !== x[p].constructor.toString() || !testEq(obj1[p], x[p], depth + 1))) return false;
                  break;
              case 'function':
                  if (p != 'equals' && obj1[p].toString() != x[p].toString()) return false;
                  break;
              default:
                  if (obj1[p] !== x[p]) return false;
          }
      }
    }
    return true;
  };
  // this is a little ugly, but the algorithm above fails the following: testEq([[1,2],[]], [[1,2],[1,3]], 0)
  return testEq(obj1, x, 0) && testEq(x, obj1, 0); 

};