diffpatchjson
v0.2.0
Published
Diff & patch JSON values, using low-footprint deltas/diffs
Downloads
4
Readme
diffpatchjson
A small JavaScript library for diffing & patching JSON values, using low-footprint deltas/diffs.
Comparison with jsondiffpatch
diffpatchjson is very similar to jsondiffpatch, the probably most popular JavaScript library for diffing & patching JSON values. So if you're reading this, there's a good chance that you are wondering how diffpatchjson compares to jsondiffpatch and which one you should choose.
The following sections describe some noteworthy differences between diffpatchjson and jsondiffpatch:
Smaller (but non-reversible) deltas/diffs
The deltas/diffs (=the data that describes the difference between the old and the new JSON value) created by diffpatchjson will almost always be smaller than those created by jsondiffpatch (after conversion to a JSON string). That's because jsondiffpatch's delta format was developed with reversibility in mind, which basically means that it is possible to unpatch a patched JSON value using the same delta/diff. diffpatchjson's delta format on the other hand is not reversible, which allows for a number of optimizations that can significantly reduce the footprint of the diffs/deltas, for example:
- When jsondiffpatch modifies a value, both the old and the new value are stored in the delta. diffpatchjson only stores the new value in such cases.
- When jsondiffpatch changes an object, the full names/keys of the changed properties are stored in the delta as strings. diffpatchjson uses shorter integer indexes to identify the property, except when a new property is being added.
There is a test page where you can enter two JSON values and see/compare the deltas/diffs produced by both diffpatchjson and jsondiffpatch.
Smaller code size, no dependencies
jsondiffpatch depends on 8 other npm packages (2 direct + 6 indirect dependencies), and the code size (including dependencies) is about 55 kB even after minification.
diffpatchjson on the other hand has no dependencies, and the minified code is only about 4 kB.
Builtin object matching
jsondiffpatch does not automatically compare arrays/objects for equality, for example when moving arrays/objects inside an array. To overcome this limitation, the user can provide an optional objectHash
function, but that usually requires some knowledge about the structure of the objects.
diffpatchjson on the other hand automatically compares objects for equality by default. Since this might be computationally expensive in some cases, one can override this default behaviour:
- by passing the
compute_object_hash
option (this is pretty much the same as theobjectHash
option in jsondiffpatch) - by passing the
are_objects_equal
option
No string diffs
Unlike jsondiffpatch, diffpatchjson (currently?) does not have an optimized delta/diff for strings, so jsondiffpatch is not well suited for diffing long strings with small changes.
No fancy features
diffpatchjson provides pretty much only the core functionality: diff
& patch
plus a few useful helper functions.
It does not provide "output formatters" for HTML, ANSI etc. and does not support plugins.
Installation
npm install diffpatchjson
Usage example
Here's a short example that shows how to use diffpatchjson:
import { are_deep_equal, diff, patch } from 'diffpatchjson';
let old_value, new_value, delta, patched_value;
old_value = {
"name": {
"first": "Max",
"last": "Masterman"
},
"date of birth": "1984-03-23"
};
new_value = {
"name": {
"first": "Max",
"last": "Mustermann"
},
"date of birth": "1984-03-23"
};
delta = diff(old_value, new_value);
console.log(JSON.stringify(delta));
// Prints: [2,[2,["Mustermann"]]]
patched_value = patch(old_value, delta);
console.log(are_deep_equal(new_value, patched_value));
// Prints: true
API
Remember to import
:
import { are_deep_equal, deep_clone, diff, patch } from 'diffpatchjson';
...or require
:
const { are_deep_equal, deep_clone, diff, patch } = require('diffpatchjson');
...the functions you intend to use.
diff
diff(old_value, new_value [, diff_options])
Computes and returns the delta/difference between the JSON values old_value and new_value. The returned delta/diff is a JSON value as well.
diff options
diff
accepts an optional third object argument for passing options. Right now, the following options are supported:
are_objects_equal
In order to check two objects for equality, you can pass a function as the are_objects_equal
option. The function will be called with two objects as arguments, and shall return true
if these objects are considered equal.
import { diff } from 'diffpatchjson';
diff(old_value, new_value, {
are_objects_equal: (object_1, object_2) = (object_1 === object_2),
})
The module exports an are_strict_equal
function by the way that does just the above:
import { are_strict_equal, diff } from 'diffpatchjson';
diff(old_value, new_value, {
are_objects_equal: are_strict_equal,
})
compute_object_hash
As an alternative to providing the are_objects_equal
option, you can provide an compute_object_hash
option. This works pretty much identical to the objectHash
option that you may know from jsondiffpatch. The function will be called with an object as argument, and must return a "hash" value that should be the same for all objects that are considered equal.
This usually requires some knowledge about the internal structure of the objects you are diffing:
import { diff } from 'diffpatchjson';
diff(old_value, new_value, {
compute_object_hash: (object) = object.id,
})
The default behaviour of diffpatchjson by the way is that the "hash" of an object is simply a JSON string representation of the object:
import { diff, stringify_json_value } from 'diffpatchjson';
diff(old_value, new_value, {
compute_object_hash: stringify_json_value,
})
The results are being cached, so the function you pass as the compute_object_hash
option will only be called once for each object.
patch
patch(old_value, delta)
Patches old_value with a delta (created by the diff
function) and returns the new/patched value.
are_deep_equal
are_deep_equal(value_1, value_2)
Helper function that compares value_1 and value_2 and returns a boolean value indicating if the values are "deep-equal". In JavaScript, booleans, numbers, strings etc. can easily be compared for equality using the strict equality operator ===
(e.g. "foo" === "foo"
is true
), but objects cannot (e.g. {a:1} === {a:1}
is false
). The are_deep_equal
function can help in such cases (e.g. are_deep_equal({a:1}, {a:1})
is true
).
deep_clone
deep_clone(value)
Helper function that returns a deep-cloned copy of the JSON value value.