Search code examples
javascriptlodash

Simple way to compare two objects with unknown stuctures


Let's say I have object which describes expected result:

{
"property1" : "value1",
"property2" : "value2",
    "property3" :{
        "property4" : "value4"
    }
}

I don't care about all the extra properties. For example,in this case, I get actual result like this, and it will be a match, as all expected properties are present and have expected values:

{
   "property1":"value1",
   "property2":"value2",
   "property3":{
      "property4":"value4",
      "property5":"value5"
   },
   "property6":"value6"
}

And this will not be a match:

{
   "property2":"value20",
   "property3":{
      "property4":"value4"
   }
}

Difficult part here is that I don't know structure in advance; I need a function that would match any objects.

My best idea so far is to use lodash merge to flatten both objects so they look like this:

{
       "property1":"value1",
       "property2":"value2",
       "property3.property4":"value4",
       "property3.property5":"value5",
       "property6":"value6"
}

After which I can just cycle on all expected properties. This solution feels awkward, though; is there a simpler, easier way to accomplish this?


Solution

  • Simple way using Lodash's by transform function to iterate over each key-value pair in the input object, and checks if the value is an object using isObject. If the value is an object, the implementation creates a nested object using transform again, with a function that concatenates the key with the nested key using dot notation. The nested object is then merged with the result object using assign:

    const _ = require('lodash');
    const flattenedObj = _.transform(myObj, function (result, value, key) {
      if (_.isObject(value)) {
        const nestedObj = _.transform(value, function (nestedResult, nestedValue, nestedKey) {
          nestedResult[key + '.' + nestedKey] = nestedValue;
        });
        _.assign(result, nestedObj);
      } else {
        result[key] = value;
      }
    });