Package Exports
- jsondiffpatch
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (jsondiffpatch) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
JsonDiffPatch
Diff & Patch for JavaScript objects and arrays (ie. any JSON serializable structure)
JsonDiffPatch is a small library that allows to diff object graphs, create a patch (in pure JSON), and apply it to update an original version.
Now available on npm:
npm install jsondiffpatchor
bower install jsondiffpatchDEMO
- Could be used for logging, audit, remote (client-server) synchronization of changes, etc.
- Minified version is < 6KB
- Works in browsers and server (Node.j or any CommonJS env), open test page to check other browsers.
- Automatically detect environment support and load as CommonJS module (eg: node.js), anonymous AMD module (eg: using RequireJS on the browser, no globals), or as browser global.
- For long text diffs uses google-diff_match_patch library if loaded (other text diff libs can be plugged in)
- Arrays diffs are smart!
- Using LCS (the same type of algorithm used by popular text diff tools on lines of text) insertions and deletions are detected efficiently.
- Also detects items moved on the same array (a refinement to LCS). Patching will only move the item in the array, and inner changes in the moved object are diffed/patched too.
- Works with objects in the array if you provide a hash function, eg:
jsondiffpatch.config.objectHash = function(obj) { return obj.id || JSON.stringify(obj); };. NOTE: If no objectHash function is configured Array items are compared using just===, meaning{ a: 1 }is different from{ a: 1 }unless they reference the same instance, this is by design, because object equality is a problem without trivial solution. Some use-cases are fine with just===(the default), others need comparison by an id field, others full JSON stringify, be sure to provide yours if default is not enough, as in DEMO page)
- Reverse a diff and unpatch (eg. revert object to its original state based on diff)
- Optional lib included for visualizing diffs as html
Delta Legend
Objects on the graph means that it's a node in the diff tree and will continue recursively
_t: (special member) indicates the type of node,ameansarray, otherwise it's anobject.- in arrays,
Nindicates index on the new array,_Nmeans index at the original array.
Arrays in the delta means that the node has changed
[newValue]-> added[oldValue, newValue]-> modified[oldValue, 0, 0]-> deleted[textDiff, 0, 2]-> text diff["", N, 3]-> element was moved to N
###Example
Object diffing:
// sample data
var country = {
name: "Argentina",
capital: "Buenos Aires",
independence: new Date(1816, 6, 9),
unasur: true
};
// clone country, using dateReviver for Date objects
var country2 = JSON.parse(JSON.stringify(country),jsondiffpatch.dateReviver);
// make some changes
country2.name = "Rep�blica Argentina";
country2.population = "41324992";
delete country2.capital;
var delta = jsondiffpatch.diff(country,country2);
/*
delta = {
"name":["Argentina","Rep�blica Argentina"], // old value, new value
"population":["41324992"], // new value
"capital":["Buenos Aires",0,0] // deleted
}
*/
// patch original
jsondiffpatch.patch(country, delta);
// reverse diff
var reverseDelta = jsondiffpatch.reverse(delta);
// also country2 can be return to original value with: jsondiffpatch.unpatch(country2, delta);
var delta2 = jsondiffpatch.diff(country,country2);
// delta2 is undefined, no differenceArray diffing:
// sample data
var country = {
name: "Argentina",
cities: [
{
name: 'Buenos Aires',
population: 13028000,
},
{
name: 'C�rdoba',
population: 1430023,
},
{
name: 'Rosario',
population: 1136286,
},
{
name: 'Mendoza',
population: 901126,
},
{
name: 'San Miguel de Tucum�n',
population: 800000,
}
]
};
// clone country
var country2 = JSON.parse(JSON.stringify(country));
// delete C�rdoba
country.cities.splice(1, 1);
// add La Plata
country.cities.splice(4, 0, {
name: 'La Plata'
});
// modify Rosario, and move it
var rosario = country.cities.splice(1, 1)[0];
rosario.population += 1234;
country.cities.push(rosario);
// match objects by name
jsondiffpatch.config.objectHash = function(obj) {
return obj.name;
}
var delta = jsondiffpatch.diff(country,country2);
/*
delta = {
"cities": {
"1": [
// inserted at index 1
{
"name": "C�rdoba",
"population": 1430023
}]
,
"2": {
// population modified at index 2 (Rosario)
"population": [
1137520,
1136286
]
},
"_t": "a",
"_3": [
// removed from index 3
{
"name": "La Plata"
},0,0],
"_4": [
// move from index 4 to index 2
'',2,3]
}
}
*/For more complex cases (nested objects or arrays, long text diffs) check unit tests in /test/test.js
To use as AMD module (eg: using RequireJS on the browser):
require('jsondiffpatch', function(jsondiffpatch){
// code using jsondiffpatch
});
// a module that depends on jsondiffpatch
define('mytexteditor.visualcomparer', ['jsondiffpatch'], function(jsondiffpatch){
// module implementation using jsondiffpatch
});Targeted platforms
- Tested on Chrome, FireFox, IE7+, to check other browsers open test page to run unit tests.
- Node.js
QUnit is used for unit testing. Just open the test page on your preferred browser.
To run tests on Node.js on jsondiffpatch root folder:
npm i
npm testMinification
A minified version is provided as jsondiffpatch.min.js To regenerate that file run (npm i is required as uglifyjs is used):
npm i
npm run-script minifyIncluding JsonDiffPatch in your application
Install using npm:
npm install jsondiffpatchor, Download the latest release from the web site (http://github.com/benjamine/JsonDiffPatch) and copy
jsondiffpatch.min.js to a suitable location. To support text diffs include Google's diff_match_patch.
Then include it in your HTML like so:
<script type="text/javascript" src="/path/to/jsondiffpatch.min.js"></script>
<script type="text/javascript" src="/path/to/diff_match_patch_uncompressed.js"></script>Note: you can use JsonDiffPatch on browserless JavaScript environments too (as Node.js, or Mozilla Rhino).
On Node.js you have to connect your text diff/patch library explicitly. eg:
var jsondiffpatch = require('./jsondiffpatch.js');
// load google diff_match_patch library for text diff/patch
jsondiffpatch.config.diff_match_patch = require('./diff_match_patch_uncompressed.js');
// use text diff for strings longer than 5 chars
jsondiffpatch.config.textDiffMinLength = 5;
var d = jsondiffpatch.diff({ age: 5, name: 'Arturo' }, {age: 7, name: 'Armando' });
// d = {
// age: [ 5, 7 ],
// name: [ '@@ -1,6 +1,7 @@\n Ar\n-tur\n+mand\n o\n', 0, 2 ] }
console.log(d.name[0])
// prints:
// @@ -1,6 +1,7 @@
// Ar
// -tur
// +mand
// oVisual Diff
To visualize diffs you can include JsonDiffPatch.Html script + css on your page:
<script type="text/javascript" src="/path/to/jsondiffpatch.html.js"></script>
<link rel="stylesheet" href="../src/jsondiffpatch.html.css" type="text/css" />Now you can use the jsondiffpatch.html.diffToHtml() function to visualize diffs as html:
var json1 = JSON.parse($('#json1').val());
var json2 = JSON.parse($('#json2').val());
var d = jsondiffpatch.diff(json1, json2);
$('#myvisualdiffcontainer').empty().append(jsondiffpatch.html.diffToHtml(json1, json2, d));To see this in action check the DEMO page.
Also you can generate diffs with jsondiffpatch on your console:
jsondiffpatch .\test\testdata.json .\test\testdata2.json