Search code examples
javascriptjsoncomparelodash

JSON comparison neglecting data/values & considering only properties/keys


Comparing two json objects neglecting the data (values) and considering only the keys/properties (structure). I used isEqual from lodash. which is good. It will neglect the keys order. What I would need is a way to neglect the values and comparing only the structure of the two jsons.

That is

  1. Removing the data
  2. Comparing the structures

This comparison should ideally return true.

var _ = require('lodash');

const object1 = {
  name: 'Tom',
  address: 'USA'
};
    
const object2 = {
  name: 'Kumar',
  address: 'India',
};

const comparison = _.isEqual(object1 ,object2)
console.log('Is comparison ?', comparison)

Solution

  • Lodash doesn't have an out of the box function that compare keys equality, but you can create one by comparing the number of keys in each objects, and if they are the same check that they are equal to the combined keys number (using a Set):

    const isEqualKeys = (a, b) => {
      const keysA = Object.keys(a);
      const keysB = Object.keys(b);
      
      return keysA.length === keysB.length // has the same length of keys
        && new Set([...keysA, ...keysB]).size === keysA.length // has the same length to the combined keys
    };
    
    const o1 = { name: 'Tom', address: 'USA' };
    const o2 = { name: 'Kumar', address: 'India' };
    const o3 = { name: 'Tom', country: 'USA' };
    const o4 = { name: 'Tom', address: 'USA', gender: "f" };
    const o5 = { name: 'Kumar' };
    
    console.log(isEqualKeys(o1, o2)); // true
    console.log(isEqualKeys(o1, o3)); // false
    console.log(isEqualKeys(o1, o4)); // false
    console.log(isEqualKeys(o1, o5)); // false

    Recursive solution to compare nested objects. The check is only performed if both values are objects, if one of them is an object and the other not, we ignore the values:

    const isEqualKeys = (a, b) => {
      const keysA = Object.keys(a);
      const keysB = Object.keys(b);
      
      const combinedKeys = new Set([...keysA, ...keysB]);
      
      return keysA.length === combinedKeys.size 
        && keysB.length === combinedKeys.size
        && [...combinedKeys].every(key => {
          const typeA = typeof(a[key]);
          const typeB = typeof(b[key]);
          
          if(typeA === 'object' && typeB === 'object') return isEqualKeys(a[key], b[key]);
          
          return true;
        })
    };
    
    const o1 = { name: 'Tom', address: 'USA' };
    const o2 = { name: 'Kumar', address: 'India' };
    const o3 = { name: 'Tom', country: 'USA' };
    const o4 = { name: 'Tom', address: 'USA', gender: "f" };
    const o5 = { name: 'Kumar' };
    
    const o6 = { name: 'Kumar', b: { c: 5 } };
    const o7 = { name: 'Kumar', b: { c: 7 } };
    const o8 = { name: 'Kumar', a: 1 };
    const o9 = { name: 'Kumar', b: 1 };
    const o10 = { name: 'Kumar', b: { d: 7 } };
    
    console.log(isEqualKeys(o1, o2)); // true
    console.log(isEqualKeys(o1, o3)); // false
    console.log(isEqualKeys(o1, o4)); // false
    console.log(isEqualKeys(o1, o5)); // false
    console.log(isEqualKeys(o6, o7)); // true
    console.log(isEqualKeys(o6, o8)); // false
    console.log(isEqualKeys(o6, o9)); // true
    console.log(isEqualKeys(o6, o10)); // false