Top community members
All Wiki Articles Create Wiki Article

In the past we had a dream,
to have place where we could share IT knowledge,
to ask questions without fear that someone will judge us.

Now we are a group of people who make this dream come true. ❤ 💻

If you think sharing knowledge and helping other is valuable.

join our community - Click here

JavaScript - how to write own compare jsons function?

0 contributions
5 points

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. 

1. Custom diff method 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,
  };
}

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

var createCreatedItem = function(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));

Formatted result:

{
   "name": null,
   "status": "unchanged",
   "oldType": "object",
   "newType": null,
   "oldValue": [
      {
         "name": "name",
         "status": "unchanged",
         "oldType": "simple",
         "newType": null,
         "oldValue": "John",
         "newValue": null
      },
      {
         "name": "items",
         "status": "unchanged",
         "oldType": "array",
         "newType": null,
         "oldValue": [
            {
               "name": "0",
               "status": "updated",
               "oldType": "simple",
               "newType": "simple",
               "oldValue": 1,
               "newValue": "1"
            },
            {
               "name": "1",
               "status": "unchanged",
               "oldType": "simple",
               "newType": null,
               "oldValue": 2,
               "newValue": null
            },
            {
               "name": "2",
               "status": "updated",
               "oldType": "simple",
               "newType": "simple",
               "oldValue": "3",
               "newValue": 3
            },
            {
               "name": "3",
               "status": "unchanged",
               "oldType": "object",
               "newType": null,
               "oldValue": [
                  {
                     "name": "name",
                     "status": "updated",
                     "oldType": "simple",
                     "newType": "simple",
                     "oldValue": "Item",
                     "newValue": "Item 2"
                  },
                  {
                     "name": "z",
                     "status": "deleted",
                     "oldType": "array",
                     "newType": null,
                     "oldValue": [
                        {
                           "name": "0",
                           "status": "deleted",
                           "oldType": "simple",
                           "newType": null,
                           "oldValue": 4,
                           "newValue": null
                        }
                     ],
                     "newValue": null
                  },
                  {
                     "name": "x",
                     "status": "created",
                     "oldType": null,
                     "newType": "simple",
                     "oldValue": null,
                     "newValue": 3
                  }
               ],
               "newValue": null
            },
            {
               "name": "4",
               "status": "deleted",
               "oldType": "simple",
               "newType": null,
               "oldValue": 5,
               "newValue": null
            }
         ],
         "newValue": null
      }
   ],
   "newValue": null
}

 

0 contributions

Checkout latest Findings & News:

Checkout latest questions:

Checkout latest wiki articles:

Hey 👋
Would you like to know what we do?
  • Dirask is IT community, where we share coding knowledge and help each other to solve coding problems.
  • We welcome everyone,
    no matter what the experience,
    no matter how basic the question is,
    this community will help you.
Read more