有没有可能比较两个json对象的差异?目前有一个脚本正在通过jquery $post()轮询JSON对象。我想做的是,将刚刚轮询的对象与存储的对象进行比较。如果有任何更改,就将它们应用于存储的对象或替换它(无论哪种方式),但从UI的角度来看,将更改无缝地应用于JSON对象,找到两者之间的差异。我想这样做是因为现在我已经让UI每次轮询时完全重新加载,无论是否更改都会这样做,这基本上看起来像UX **。我认为,如果我能找到两个对象之间的差异,我就会触发一个函数,该函数会根据差异编辑UI。
old: {"mum" : "Maria", "dad" : "Pierre", "kids" : ["Joe", "Mike", "Louisa"] }
new: {"mum" : "Julie", "dad" : "Pierre", "kids" : ["Joe", "Mary"] }
这个差异是不是 {"mum" : "Julie", "kids" : ["Mary"]}
? "mum"属性已经改变,"kids"列表也发生了变化,但是"Mike"是否变成了"Mary",还是"Mike"和"Louisa"都消失了而"Mary"是新的呢?也许应该是 "kids": ["Joe","Mary"]
,因为这是新值。如何指示删除的内容呢?这只是我脑海中的第一个例子,我不知道您希望如何处理这些差异。情况可能会更糟:如果"kids"数组包含对象而不是字符串来表示整个家庭树怎么办?如果新的"mum"属性是["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]))
在网络或者StackOverflow上有很多比较函数,其中isEqual()
是其中之一。
(注意:我没有使用.hasOwnProperty()
,因为我认为作为 JSON 返回给 Ajax 请求的对象不会从原型链继承属性。类似地,这样用于此目的的isEqual()
函数无需考虑属性是函数,它只需要关心在 JSON 字符串中有效的内容。)
很抱歉回答旧帖,但我的回答可能会帮助其他可能遇到同样问题的人。以下是比较两个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>
var newJSON = $.extend({},oldJSON,serverData);
那么你将会保留旧对象,并创建一个新对象,如果在新对象中没有旧对象的任何属性,则使用旧对象的属性,并用来自服务器的新数据覆盖任何现有属性。
var newJSON = serverData
。 - Raynosvar 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);
};
这是我的代码:
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;
}
我们获取元素的类型并进行内部比较以确定它们是否相等。