获取两个 json 对象的差异
场景:我想要一个比较两个 JSON 对象的函数,并返回一个包含差异列表的 JSON 对象,如果可能的话还返回更多数据,例如覆盖率指标。
var madrid = '{"type":"team","description":"Good","trophies":[{"ucl":"10"}, {"copa":"5"}]}';
var barca = '{"type":"team","description":"Bad","trophies":[{"ucl":"3"}]}';
如果我运行 compare(madrid, barca)
返回的对象可能看起来像:
{"description" : "Bad", "trophies":[{"ucl":"3"}, {"copa":"5"}]};
或者类似的东西,你明白了。
有谁知道这个问题的解决方案?我已经找到一个 插件,但我想知道是否有其他选择。
Scenario: I want a function that compares two JSON-objects, and returns a JSON-object with a list of the differences and if possible more data such as coverage metrics.
var madrid = '{"type":"team","description":"Good","trophies":[{"ucl":"10"}, {"copa":"5"}]}';
var barca = '{"type":"team","description":"Bad","trophies":[{"ucl":"3"}]}';
If i ran compare(madrid, barca)
the returned object could look something like:
{"description" : "Bad", "trophies":[{"ucl":"3"}, {"copa":"5"}]};
Or something similar, you get the idea.
Does anyone know of a solution to this? I've already found one plugin, but I'd like to know if there are any alternatives.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
可以使用按对象键进行迭代的递归函数。然后使用 Object.is 来测试
NaN
和null
。然后测试第二个对象是否是转换为false
的类型,例如0
、NaN
或null
。列出两个对象的键并将它们连接起来以测试 obj1 中缺少的键,然后迭代它。
当相同键值之间存在差异时,它存储
object2
的值并继续。如果两个键值都是对象,则意味着可以递归比较,所以确实如此。上面的代码是 BSD 许可的,可以在任何地方使用。
测试链接: https://jsfiddle.net/gartz/vy9zaof2/54/
一个重要的观察是,这会将数组转换为对象并比较相同索引位置的值。由于需要额外的复杂性,还有许多其他方法可以比较此函数未涵盖的数组。
编辑 2019 年 2 月 15 日:此答案已更改以添加新的 ES2017 语法并修复来自
这只是一个开始,我还没有测试过它,但我从一个过滤器或比较器函数开始,它是递归的,可以根据需要更改它以获得优先结果。
测试:http://jsfiddle.net/gartz/Q3BtG/2/
It's possible to use a recursive function that iterates by the object keys. Then use the Object.is to test for
NaN
andnull
. Then test if the second object is the type that cast tofalse
like0
,NaN
, ornull
.List the keys of both objects and concatenate them to test of missing keys in the
obj1
and then iterate it.When there is a difference between the same key values, it stores the value of
object2
and proceeds. If both key values are object means that can be recursively compared and so it does.The code above is BSD licensed and can be used anywhere.
Test link: https://jsfiddle.net/gartz/vy9zaof2/54/
An important observation, this will convert arrays to objects and compare the values in the same index position. There are many other ways to compare arrays not covered by this function due to the required extra complexity.
EDIT 2/15/2019: This answer was changed to add the new ES2017 syntax and fix use-cases from comments.
This is just a kickoff, I haven't tested it, but I began with a filter or comparator function, that is recursive, change it however you need to get priority results.
Tests: http://jsfiddle.net/gartz/Q3BtG/2/
贡献我对 Gabriel Gartz 版本的更改。这个在严格模式下工作并删除数组检查 - 将始终为 false。它还从差异中删除空节点。
contributing back my changes to Gabriel Gartz version. This one works in strict mode and removes the array check - will always be false. It also removes empty nodes from the diff.
您可以使用 rus-diff https://github.com/mirek/node-rus-diff 创建 MongoDB 兼容(重命名/取消设置/设置)差异:
输出:
You can use rus-diff https://github.com/mirek/node-rus-diff which creates MongoDB compatible (rename/unset/set) diff:
Outputs:
对 Gabriel Gartz 版本的又一修改。此显示元组
[oldValue, newValue]
中每个键之前/之后的值,并且不包含差异中的空分支One more modification to Gabriel Gartz's version. This one shows both values before/after for each key in a tuple
[oldValue, newValue]
and doesn't include empty branches in the diff对我来说这有效:
For me this worked:
存在以下三种情况:
两个对象上都存在属性。
删除
它(复制
)。第一个对象(
原始
)上存在属性,但第二个对象上不存在该属性。在本例中,将该属性添加到第二个对象。最后,第二个对象上存在一个属性,但第一个对象上不存在,在这种情况下,不执行任何操作。
There are these three scenarios:
A property exists on both the objects.
delete
it from the second object (copy
).A property exists on the first object (
original
), but not on the second object. In this case add the property to the second object.And finally a property exists on the second object but not on the first, in this case, do nothing.
我遇到了同样的挑战,并创建了一个轻量级 API 来执行此操作,因为我发现其他 API 太复杂了 -获取对象之间的差异,以及将差异合并回 json 数据的能力。看起来它完全满足您的需要:
diff 对象使用 __deleted 或 __mergeAction 等标签来跟踪对象的更改,例如删除的数组记录或数组中的新/更新记录。否则,更改的非对象键(例如示例中的描述字段)只会显示在增量中。
I had the same challenge and created a light API to do this as I found the others too complex -- get diff between objects, and ability to merge a diff back into json data. Looks like it does exactly what you need:
The diff object uses tags like __deleted or __mergeAction to keep track what the change is for an object such as a deleted array record, or a new / updated record in an array. Otherwise non-object keys that change (such as the description field in your example) just show up in the delta.