JSON Patch using Underscore
HTML
<script src="http://underscorejs.org/underscore-min.js"></script>
<script src="https://raw.github.com/bruth/jsonpatch-js/master/jsonpatch.js"></script>
JavaScript
var obj1 = {
4: 'e',
1: ['a', 'c', 5]
};
var obj2 = {
5: ['a', 'c', 5],
2: {
4: 'e'
},
3: 'b',
};
// Patch helper functions
function getParent(paths, path) {
return paths[path.substr(0, path.match(/\//g).length)];
}
// Checks if `obj` is an array or object
function isContainer(obj) {
return _.isArray(obj) || _.isObject(obj);
}
// Checks if the two objects are of the same container type
function isSameContainer(obj1, obj2) {
return (_.isArray(obj1) && _.isArray(obj2)) || (_.isObject(obj1) && _.isObject(obj2));
}
// Flattens an object to a hash of paths and values.
function flattenObject(obj, prefix, paths) {
prefix || (prefix = '/');
paths || (paths = {});
// Do not bother logging the root path
paths[prefix] = {
path: prefix,
value: obj
};
prefix !== '/' && (prefix = prefix + '/')
// Recurse for container types
if (_.isArray(obj)) {
for (var i = 0, l = obj.length; i < l; i++) {
flattenObject(obj[i], prefix + i, paths);
}
} else if (_.isObject(obj)) {
for (var key in obj) {
flattenObject(obj[key], prefix + key, paths);
}
}
return paths;
}
// Constructs a patch that when applied to `obj2`, it will be equivalent
// to `obj1`. The patch format conforms to IETF JSON Patch proposal
// http://tools.ietf.org/html/draft-ietf-appsawg-json-patch-01
function constructPatch(obj1, obj2) {
// Patches are only applicable to two of the same container types.
if (!isSameContainer(obj1, obj2)) {
throw new Error('Patches can only be derived from objects or arrays');
}
var paths1 = flattenObject(obj1),
paths2 = flattenObject(obj2),
key1,
key2,
doc1,
doc2,
patch = [],
add = {},
remove = {},
replace = {},
move = {};
// Iterate over the first object's paths and compare them to the second
// set of paths.
for (key1...