【发布时间】:2011-11-11 16:42:01
【问题描述】:
是否有标准库或工具用于计算和应用 JSON 文档的差异?基本上我有一堆大型文档,我想在网络上保持同步,并且我希望避免每次我想要同步它们时都重新发送它们的整个状态(因为其中许多变量不会改变)。换句话说,我只想传输改变的字段,而不是重新传输整个对象。我认为拥有以下一组方法会很方便:
//Start with two distinct objects on the server
// prev represents a copy of the state of the object on the client
// next represents a copy of the state of the object on the server
//
//1. Compute a patch
patch = computePatch(prev, next);
//2. Send patch over the network
//3. Apply the patch on the client
applyPatch(prev, patch);
//Final invariant:
// prev represents an equivalent object to JSON.parse(JSON.stringify(next))
我当然可以自己实现一个,但有很多边缘情况需要考虑。以下是我能想到的一些简单(虽然有些不满意)的方法,例如:
滚动我自己的 JSON 修补程序。渐近地,这可能是最好的方法,因为它可以支持 JSON 文档的所有相关特性,同时支持一些专门的方法来做一些事情,比如区分整数、双精度和字符串(使用相对编码/编辑距离) .但是,JSON 有很多特殊情况,我对在没有大量测试的情况下尝试这样做有点怀疑,所以我更愿意找到已经为我解决这个问题的东西,以便我可以信任它,并且不必担心由于我的 JSON 补丁错误而出现网络 Heisenbugs
只需使用动态编程直接计算 JSON 字符串之间的编辑距离。不幸的是,如果客户端和服务器具有不同的 JSON 实现(即它们的字段的顺序可以不同地序列化),这将不起作用,并且作为二次时间操作也非常昂贵。
使用协议缓冲区。协议缓冲区有一个内置的 diff 方法,它完全符合我的要求,它们是一种很好的二进制可序列化网络友好格式。不幸的是,因为它们也是严格类型的,所以它们缺乏使用 JSON 的许多优点,例如动态添加和删除字段的能力。目前这是我目前倾向于使用的方法,但它可能会使未来的维护变得非常糟糕,因为我需要不断更新我的每个对象。
做一些非常讨厌的事情,比如为每种类型的对象创建一个自定义协议,并希望我在这两个地方都能做到(是的!)。
当然,我真正希望的是,stackoverflow 上的某个人能够通过引用节省空间的 javascript 对象differ/patcher 来拯救这一天,该对象已在生产环境和多个浏览器中经过良好测试。
*更新*
我开始编写自己的补丁程序,它的早期版本可以在 github 上找到:
https://github.com/mikolalysenko/patcher.js
我想因为这里似乎没有太多内容,所以我会接受 JSON 修补程序的有趣测试用例列表作为替代答案。
【问题讨论】:
-
既然您提到了“需要考虑的相当多的边缘情况”,如果您列举需要处理哪些边缘情况以及如何处理可能会有所帮助(对您的答案和后代而言)他们应该得到解决。
-
旁白:你问题的后半部分很好地表明你已经考虑过这个问题,并且作为“解决方法”答案的一部分可能很好,但与问题无关,对吧?
-
总是添加一个
dirty标志。 -
有
dirty标志?我没看到。 -
“大”的定义很重要,以及它们如何变化很重要。除非你有大量的文档,并且一直有大量的微小变化,否则这可能是过早的优化。
标签: javascript json node.js