我希望能够获得两个JavaScript对象图之间所有差异的列表,以及发生增量的属性名称和值.
对于它的价值,这些对象通常作为JSON从服务器中检索,并且通常只有少数深层(即它可能是一个对象数组,它们本身具有数据,然后是与其他数据对象一起的数组).
我想不仅要看到基本属性的更改,还要看到数组成员数量的差异等.
如果我没有得到答案,我可能最终会自己写这篇文章,但希望有人已经完成了这项工作或者知道有人.
编辑:这些对象通常在结构上彼此非常接近,所以我们不是在讨论彼此完全不同的对象,而是可能有3或4个增量.
这是我的问题的一个部分,天真的解决方案 - 我将在我进一步开发它时更新它.
function findDifferences(objectA, objectB) { var propertyChanges = []; var objectGraphPath = ["this"]; (function(a, b) { if(a.constructor == Array) { // BIG assumptions here: That both arrays are same length, that // the members of those arrays are _essentially_ the same, and // that those array members are in the same order... for(var i = 0; i < a.length; i++) { objectGraphPath.push("[" + i.toString() + "]"); arguments.callee(a[i], b[i]); objectGraphPath.pop(); } } else if(a.constructor == Object || (a.constructor != Number && a.constructor != String && a.constructor != Date && a.constructor != RegExp && a.constructor != Function && a.constructor != Boolean)) { // we can safely assume that the objects have the // same property lists, else why compare them? for(var property in a) { objectGraphPath.push(("." + property)); if(a[property].constructor != Function) { arguments.callee(a[property], b[property]); } objectGraphPath.pop(); } } else if(a.constructor != Function) { // filter out functions if(a != b) { propertyChanges.push({ "Property": objectGraphPath.join(""), "ObjectA": a, "ObjectB": b }); } } })(objectA, objectB); return propertyChanges; }
这里有一个如何使用它和它将提供的数据的样本(请原谅长的例子,但我想使用一些相对非平凡的东西):
var person1 = { FirstName : "John", LastName : "Doh", Age : 30, EMailAddresses : [ "john.doe@gmail.com", "jd@initials.com" ], Children : [ { FirstName : "Sara", LastName : "Doe", Age : 2 }, { FirstName : "Beth", LastName : "Doe", Age : 5 } ] }; var person2 = { FirstName : "John", LastName : "Doe", Age : 33, EMailAddresses : [ "john.doe@gmail.com", "jdoe@hotmail.com" ], Children : [ { FirstName : "Sara", LastName : "Doe", Age : 3 }, { FirstName : "Bethany", LastName : "Doe", Age : 5 } ] }; var differences = findDifferences(person1, person2);
此时,differences
如果将序列化为JSON ,则数组的外观如下:
[ { "Property":"this.LastName", "ObjectA":"Doh", "ObjectB":"Doe" }, { "Property":"this.Age", "ObjectA":30, "ObjectB":33 }, { "Property":"this.EMailAddresses[1]", "ObjectA":"jd@initials.com", "ObjectB":"jdoe@hotmail.com" }, { "Property":"this.Children[0].Age", "ObjectA":2, "ObjectB":3 }, { "Property":"this.Children[1].FirstName", "ObjectA":"Beth", "ObjectB":"Bethany" } ]
的this
在Property
值是指被比较的对象的根.因此,该解决方案还没有正是我所需要的,但它是相当的接近.
希望这对那里的人有用,如果你有任何改进的建议,我全心全意; 我昨晚很晚才写到这个(即今天凌晨),我可能会完全忽视这些事情.
谢谢.
在查看现有答案后,我注意到https://github.com/flitbit/diff库尚未列为解决方案.
从我的研究来看,这个库在积极开发,贡献和分叉方面似乎是最好的,可以解决差异对象的挑战.这对于在服务器端创建差异并仅向客户端传递更改的位非常方便.
有一个objectDiff库,允许您这样做.在其演示页面上,您可以看到两个javascript对象之间的差异.
您还可以尝试rus-diff https://github.com/mirek/node-rus-diff,它会生成MongoDB兼容(重命名/取消设置/设置)差异.
对于您的示例对象:
var person1 = { FirstName: "John", LastName: "Doh", Age: 30, EMailAddresses: ["john.doe@gmail.com", "jd@initials.com"], Children: [ { FirstName: "Sara", LastName: "Doe", Age: 2 }, { FirstName: "Beth", LastName: "Doe", Age: 5 } ] }; var person2 = { FirstName: "John", LastName: "Doe", Age: 33, EMailAddresses: ["john.doe@gmail.com", "jdoe@hotmail.com"], Children: [ { FirstName: "Sara", LastName: "Doe", Age: 3 }, { FirstName: "Bethany", LastName: "Doe", Age: 5 } ] }; var rusDiff = require('rus-diff').rusDiff console.log(rusDiff(person1, person2))
它会生成一组集:
{ '$set': { 'Age': 33, 'Children.0.Age': 3, 'Children.1.FirstName': 'Bethany', 'EMailAddresses.1': 'jdoe@hotmail.com', 'LastName': 'Doe' } }