是否可以比较两组json对象的区别?我所拥有的是一个通过jquery $ post()轮询JSON对象的脚本。我想要做的是获取刚刚轮询的对象并将其与存储的对象进行比较。如果从一个到另一个的任何变化将它们应用于存储的对象或替换它(以任何一种方式),但是从我正在使用的UI角度来看,通过找到它们之间的差异,无缝地将更改应用于JSON对象的用途。 2.我想这样做是因为我现在拥有它所以UI完全重新加载每个轮询,无论是否有变化,从UX角度来看基本上看起来像 * *。
我想如果我能找到两个对象之间的差异,我会触发一个函数,我会编辑特定于差异的UI。
答案 0 :(得分:10)
我想要做的是获取刚刚轮询的对象并将其与存储的对象进行比较。如果从一个到另一个的任何变化,将它们应用于存储的对象或替换它(无论哪种方式)
如果您对一个非常简单的“它有任何变化吗?是/否”解决方案感到高兴,如果它已经改变了,您只需将新对象替换为新对象(根据您的问题部分,我引用了,然后您可以在解析之前保存JSON响应,即将其保存为您的Web服务器发送它的字符串格式。然后当下一个响应进来时将新字符串与旧字符串进行比较。如果它们不同(或者如果它是第一个请求),则解析JSON并根据需要对其进行处理以进行显示。当然,这假设您的服务器端代码以一致的格式创建JSON字符串(而不是,例如,更改属性的顺序)。
如果我们假设你已经得到(已解析)对象,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"] }
差异是{"mum" : "Julie", "kids" : ["Mary"]}
吗? “妈妈”已经改变,“孩子”的名单已经改变了,但是“迈克”变成了“玛丽”,或者“迈克”和“路易莎”都和“玛丽”一起消失了,或者...... ?也许它应该是"kids": ["Joe","Mary"]
,因为这是新的价值。你如何表明删除?这只是我头脑中的第一个例子,我不知道你将如何处理差异。它可能很快变得更糟:如果“kids”数组包含对象而不是字符串来表示整个家族树怎么办?如果新的“妈妈”属性是["Maria", "Julie"]
(允许继父母等等),该怎么办?
如果对于您的特定数据,您知道您只有一维物体,那么您可以执行以下简单操作:
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;
}
对上面允许嵌套对象的最简单的改变是假设如果一个属性是一个对象/数组,那么你只关心它是否有任何不同而不是深入报告确切地报告哪些“子属性” “ 已经改变。如果是这样,只需采取上述功能并更改:
else if (oldObj[k] !== newObj[k])
到
else if (!isEqual(oldObj[k],newObj[k]))
其中isEqual()
是在网络上展开的众多比较函数之一或on StackOverflow。
(注意:我没有对上面的.hasOwnProperty()
感到困扰,因为我假设作为JSON返回到Ajax请求的对象不会从原型链继承属性。类似地isEqual()
函数为此目的,不需要担心属性是函数,只需要担心JSON字符串中的有效内容。)
答案 1 :(得分:4)
很抱歉回答旧帖,但我的回答可能会帮助那些可能面临同样问题的人。最简单的问题。比较两个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>
答案 2 :(得分:0)
一个可能的解决方案是使用jQuery的扩展。只要对象具有相同的属性,就可以很好地解决这个问题。
var newJSON = $.extend({},oldJSON,serverData);
然后,您将保留旧对象,并使用旧对象中的任何属性创建一个新对象(如果它们不存在于新对象中),并使用服务器中新数据的属性覆盖任何现有属性。
答案 3 :(得分:0)
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);
};
答案 4 :(得分:0)
这是我的代码:
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;
}
我们获得了元素的类型并进行了内部相等性比较。
答案 5 :(得分:-1)