How to unflatten a JavaScript object in a daisy-chain/dot notation into an object with nested objects and arrays?


Suppose, we have an object like this −

const obj = {
   "firstName": "John",
   "lastName": "Green",
   "car.make": "Honda",
   "car.model": "Civic",
   "car.revisions.0.miles": 10150,
   "car.revisions.0.code": "REV01",
   "car.revisions.0.changes": "",
   "car.revisions.1.miles": 20021,
    "car.revisions.1.code": "REV02",
   "car.revisions.1.changes.0.type":
   "asthetic",
   "car.revisions.1.changes.0.desc":
   "Left tire cap",
   "car.revisions.1.changes.1.type":
   "mechanic",
   "car.revisions.1.changes.1.desc":
   "Engine pressure regulator",
    "visits.0.date":
   "2015-01-01",
   "visits.0.dealer":
   "DEAL-001",
   "visits.1.date":
   "2015-03-01",
    "visits.1.dealer":
    "DEAL-002"
};

We are required to write a JavaScript function that takes in one such object and unflattens it into nested objects and arrays.

Therefore, the output for the above array should look like −

const output = {
   firstName: 'John',
   lastName: 'Green',
   car: {
      make: 'Honda',
      model: 'Civic',
      revisions: [
         { miles: 10150, code: 'REV01', changes: ''},
         { miles: 20021, code: 'REV02', changes: [
            { type: 'asthetic', desc: 'Left tire cap' },
            { type: 'mechanic', desc: 'Engine pressure regulator' }
         ]
      } ]
   },
   visits: [
      { date: '2015-01-01', dealer: 'DEAL-001' },
      { date: '2015-03-01', dealer: 'DEAL-002' }
   ]
};

Example

const obj = {
   "firstName": "John",
   "lastName": "Green",
   "car.make": "Honda",
   "car.model": "Civic",
   "car.revisions.0.miles": 10150,
   "car.revisions.0.code": "REV01",
   "car.revisions.0.changes": "",
      "car.revisions.1.miles": 20021,
   "car.revisions.1.code": "REV02",
   "car.revisions.1.changes.0.type":
    "asthetic",
   "car.revisions.1.changes.0.desc":
   "Left tire cap", "car.revisions.1.changes.1.type":
   "mechanic", "car.revisions.1.changes.1.desc":
   "Engine pressure regulator",
   "visits.0.date": "2015-01-01",
   "visits.0.dealer": "DEAL-001",
   "visits.1.date": "2015-03-01",
   "visits.1.dealer": "DEAL-002"
};
const unflatten = (obj = {}) => {
   const result = {};
   let temp, substrings, property, i;
   for (property in obj) {
      substrings = property.split('.');
   temp = result;
   for (i = 0; i < substrings.length - 1; i++) {
      if (!(substrings[i] in temp)) {
         if (isFinite(substrings[i + 1])) {
             temp[substrings[i]] = [];
         }
         else {
            temp[substrings[i]] = {};
         }
      }
      temp = temp[substrings[i]];
   }
   temp[substrings[substrings.length - 1]] = obj[property];
}
return result;
}; console.log(JSON.stringify(unflatten(obj), undefined, 4));

Output

And the output in the console will be −

{
   "firstName": "John",
   "lastName": "Green",
   "car": {
         "make": "Honda",
      "model": "Civic",
      "revisions": [
         {
            "miles": 10150,
            "code": "REV01",
            "changes": ""
         },
         {
            "miles": 20021,
            "code": "REV02",
            "changes": [
               {
                  "type": "asthetic",
                  "desc": "Left tire cap"
               },
               {
                  "type": "mechanic",
                  "desc": "Engine pressure regulator"
               }
            ]
         }
      ]
   },
   "visits": [
      {
         "date": "2015-01-01",
         "dealer": "DEAL-001"
      }, {
         "date": "2015-03-01",
         "dealer": "DEAL-002"
      }
   ]
}

Updated on: 21-Nov-2020

408 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements