jsondiff.js 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /**
  2. * @fileOverview
  3. *
  4. *
  5. *
  6. * @author: techird
  7. * @copyright: Baidu FEX, 2014
  8. */
  9. define(function(require, exports, module) {
  10. /*!
  11. * https://github.com/Starcounter-Jack/Fast-JSON-Patch
  12. * json-patch-duplex.js 0.5.0
  13. * (c) 2013 Joachim Wester
  14. * MIT license
  15. */
  16. var _objectKeys = (function () {
  17. if (Object.keys)
  18. return Object.keys;
  19. return function (o) {
  20. var keys = [];
  21. for (var i in o) {
  22. if (o.hasOwnProperty(i)) {
  23. keys.push(i);
  24. }
  25. }
  26. return keys;
  27. };
  28. })();
  29. function escapePathComponent(str) {
  30. if (str.indexOf('/') === -1 && str.indexOf('~') === -1)
  31. return str;
  32. return str.replace(/~/g, '~0').replace(/\//g, '~1');
  33. }
  34. function deepClone(obj) {
  35. if (typeof obj === "object") {
  36. return JSON.parse(JSON.stringify(obj));
  37. } else {
  38. return obj;
  39. }
  40. }
  41. // Dirty check if obj is different from mirror, generate patches and update mirror
  42. function _generate(mirror, obj, patches, path) {
  43. var newKeys = _objectKeys(obj);
  44. var oldKeys = _objectKeys(mirror);
  45. var changed = false;
  46. var deleted = false;
  47. for (var t = oldKeys.length - 1; t >= 0; t--) {
  48. var key = oldKeys[t];
  49. var oldVal = mirror[key];
  50. if (obj.hasOwnProperty(key)) {
  51. var newVal = obj[key];
  52. if (typeof oldVal == "object" && oldVal != null && typeof newVal == "object" && newVal != null) {
  53. _generate(oldVal, newVal, patches, path + "/" + escapePathComponent(key));
  54. } else {
  55. if (oldVal != newVal) {
  56. changed = true;
  57. patches.push({ op: "replace", path: path + "/" + escapePathComponent(key), value: deepClone(newVal) });
  58. }
  59. }
  60. } else {
  61. patches.push({ op: "remove", path: path + "/" + escapePathComponent(key) });
  62. deleted = true; // property has been deleted
  63. }
  64. }
  65. if (!deleted && newKeys.length == oldKeys.length) {
  66. return;
  67. }
  68. for (var t = 0; t < newKeys.length; t++) {
  69. var key = newKeys[t];
  70. if (!mirror.hasOwnProperty(key)) {
  71. patches.push({ op: "add", path: path + "/" + escapePathComponent(key), value: deepClone(obj[key]) });
  72. }
  73. }
  74. }
  75. function compare(tree1, tree2) {
  76. var patches = [];
  77. _generate(tree1, tree2, patches, '');
  78. return patches;
  79. }
  80. return module.exports = compare;
  81. });