Skip to content

A simple function to diff any object and generate a JSON Patch

License

Notifications You must be signed in to change notification settings

mayakarabula/generate-json-patch

 
 

Repository files navigation

generate-json-patch

Create RFC 6902 compliant JSON Patch objects based on two given JSON objects with a configurable interface.

Version Downloads/week Size Tests License TypeScript

TL;DR

  • Can diff any two JSON compliant objects - returns differences as JSON Patch.
  • Elegant array diffing by providing an objectHash to match array elements
  • Ignore specific keys by providing a propertyFilter
  • move operations are ALWAYS appended at the end, therefore, they can be ignored (if wanted) when the patch gets applied.
  • 🐾 Is it small? Zero dependencies - it's ~7 KB (uncompressed).
  • 🔮 Is it fast? I haven't done any performance comparison yet.
  • 🐥 Is it stable? Test coverage is high, but it's still in its early days - bugs are expected.
  • The interface is inspired by jsondiffpatch
  • 100% Typescript

Installation

Works on node and browser environments.

npm install generate-json-patch

Usage

import { generateJSONPatch } from 'generate-json-patch';

const before = { manufacturer: "Ford", type: "Granada", year: 1972 };
const after = { manufacturer: "Ford", type: "Granada", year: 1974 };

const patch = generateJSONPatch(before, after);

console.log(patch) // => [{op: 'replace', path: '/year', value: 1974}]

Configuration

import { generateJSONPatch, JsonPatchConfig, JsonValue } from 'generate-json-patch';

generateJSONPatch({/*...*/}, {/*...*/}, {
    // called when comparing array elements
    objectHash: function(value: JsonValue, context: GeneratePatchContext) {
        // for arrays of primitive values like string and numbers, a stringification is sufficent:
        // return JSON.stringify(value)
        // If we know the shape of the value, we can match be specific properties
        return value.name
    },
    // called for every property on objects. Can be used to ignore sensitive or irrelevant 
    // properties when comparing data.
    propertyFilter: function (propertyName: string, context: GeneratePatchContext) {
        return !['sensitiveProperty'].includes(propertyName);
    },
    array: {
        // When true, no move operations will be created. 
        // The rersulting patch will not lead to identical objects, 
        // as postions of array elements can be different!
        ignoreMove: true
    }
});

Patch Context

Both config function (objectHash, propertyFilter), receive a patch context as second parameter. This allows for granular decision-making on the provided data.

Example

import {generateJSONPatch, JsonPatchConfig, JsonValue, pathInfo} from 'generate-json-patch';

const before = {
    manufacturer: "Ford",
    type: "Granada",
    colors: ['red', 'silver', 'yellow'],
    engine: [
        { name: 'Cologne V6 2.6', hp: 125 },
        { name: 'Cologne V6 2.0', hp: 90 },
        { name: 'Cologne V6 2.3', hp: 108 },
        { name: 'Essex V6 3.0', hp: 138 },
    ]
}

const after = {
    manufacturer: "Ford",
    type: "Granada",
    colors: ['red', 'silver', 'yellow'],
    engine: [
        {name: 'Essex V6 3.0', hp: 138},
        {name: 'Cologne V6 2.6', hp: 125},
        {name: 'Cologne V6 2.0', hp: 90},
        {name: 'Cologne V6 2.3', hp: 108},
    ]
}

const patch = generateJSONPatch(before, after, {
    objectHash: function (value: JsonValue, context: GeneratePatchContext) {
        const {length, last} = pathInfo(context.path)
        if (length === 2 && last === 'engine') {
            return value.name
        }
        return JSON.stringify(value)
    }
});

console.log(patch) // => [
// { op: 'replace', path: '/engine/3/hp', value: 138 },
// { op: 'move', from: '/engine/2',  path: '/engine/3' },
// { op: 'move', from: '/engine/1',  path: '/engine/2' },
// { op: 'move', from: '/engine/0',  path: '/engine/1' }]

For more examples, check out the tests

About

A simple function to diff any object and generate a JSON Patch

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 97.9%
  • JavaScript 2.1%