Languages
[Edit]
EN

JavaScript - custom compare JSONs function

8 points
Created by:
Mikolaj
489

In this article, we're going to have a look at how to write own function to compare JSONs. Approach used in this article encloses each entity with object that keeps previous and current values with types and kind of change.

Example result:

{
    "name": "propertyName",
    "status": "changed",
    "oldType": "simple",
    "newType": "simple",
    "oldValue": "Some old value",
    "newValue": "Some new value"
}

Where:

  • status can be one of: unchanged, updated, created or deleted,
  • old and new type: array, object, simple or null,
  • old and new value: simple type object, array with enclosed entities that describe nested objects or null.

Note: read this article to see json difference visualization.

Run below example to see details. 

 

Reusable example

This section presents simple logic that returns object with difference information.

// ONLINE-RUNNER:browser;

function getType(object) {
  	return Object.prototype.toString.call(object);
}

function getDescription(type) {
    if (type == '[object Array]') {
      	return 'array';
    }
    if (type == '[object Object]') {
      	return 'object';
    }
    return 'simple';
}

function createOldItem(name, status, type, value) {
    return {
        name: name || null,
        status: status,
        oldType: getDescription(type),
        newType: null,
        oldValue: value,
        newValue: null,
    };
}

function createNewItem(name, status, type, value) {
    return {
        name: name || null,
        status: status,
        oldType: null,
        newType: getDescription(type),
        oldValue: null,
        newValue: value,
    };
}

function createDeletedItem(key, type, value) {
  	return createOldItem(key, 'deleted', type, value);
}

function createCreatedItem(key, type, value) {
  	return createNewItem(key, 'created', type, value);
}

function coverContent(entity, createItem) {
    var items = [ ];
    for (const key in entity) {
        if (entity.hasOwnProperty(key)) {
          	items.push(coverEntity(key, entity[key], createItem));
        }
    }
    return items;
}

function coverEntity(name, entity, createItem) {
    var type = getType(entity);
    if (type === '[object Array]' || type === '[object Object]') {
        var content = coverContent(entity, createItem);
        return createItem(name, type, content);
    } else {
      	return createItem(name, type, entity);
    }
}

function compareContent(a, b) {
    var items = [ ];
    for (const key in a) {
        if (a.hasOwnProperty(key)) {
            if (b.hasOwnProperty(key)) {
              	items.push(compareEntries(a[key], b[key], key));
            } else {
              	items.push(coverEntity(key, a[key], createDeletedItem));
            }
        }
    }
    for (const key in b) {
        if (b.hasOwnProperty(key)) {
            if(a.hasOwnProperty(key)){
              	continue;
            }
          	items.push(coverEntity(key, b[key], createCreatedItem));
        }
    }
    return items;
}

function compareEntries(a, b, name) {
    var oldType = getType(a);
    var newType = getType(b);
    if (a === b) {
      	return createOldItem(name, 'unchanged', oldType, a);
    }
    if (oldType == newType) {
        // both have array or object type:
        if (oldType === '[object Array]' || oldType === '[object Object]') {
            var oldValue = compareContent(a, b);
            return createOldItem(name, 'unchanged', oldType, oldValue);
        }
        // both have simple type: boolean, number, string, etc.:
        var description = getDescription(oldType);
        return {
            name: name || null,
            status: 'updated',
            oldType: description,
            newType: description,
            oldValue: a,
            newValue: b,
        };
    } else {
        // both have different types:
        var oldDescription = getDescription(oldType);
        var newDescription = getDescription(newType);
        return {
            name: name || null,
            status: 'updated',
            oldType: oldDescription,
            newType: newDescription,
            oldValue: (oldDescription == 'simple' ? a : coverContent(a, createDeletedItem)),
            newValue: (newDescription == 'simple' ? b : coverContent(b, createCreatedItem)),
        };
    }
}

function compareJsons(a, b) {
    var aEntity = JSON.parse(a);
    var bEntity = JSON.parse(b);
    return compareEntries(aEntity, bEntity);
}


// Usage example:

var json1 = '{"name":"John","items":[1,2,"3",{"name":"Item","z":[4]},5]}';
var json2 = '{"name":"John","items":["1",2,3,{"name":"Item 2","x":3}]}';

var difference = compareJsons(json1, json2);

console.log(JSON.stringify(difference, null, 4));

 

See also

  1. JavaScript - JSON difference visualization

  2. JavaScript - display object as expandable tree 

Alternative titles

  1. JavaScript - make diff on JSONs
  2. json diff operation in JavaScript
  3. JavaScript - own compare JSONs function
Donate to Dirask
Our content is created by volunteers - like Wikipedia. If you think, the things we do are good, donate us. Thanks!
Join to our subscribers to be up to date with content, news and offers.

JavaScript - JSON

Native Advertising
🚀
Get your tech brand or product in front of software developers.
For more information Contact us
Dirask - we help you to
solve coding problems.
Ask question.

❤️💻 🙂

Join