1

I need to create dynamically an object with nested objects from a string of like 'a.b.c.d' with a result as:

/*
var a = {
  b: {
    c: {
      d: {}
    }
  }
};

//or:
var result = {
  a: {
    b: {
      c: {
        d: {}
      }
    }
  }
}*/

Currently with my following script I am not able nest the objects.

What is wrong? could you provide me a solution? Thanks!

var options = 'a.b.c.d';
var parts = options.split('.');
var obj = {};
var addNestedProp = function(obj, prop) {
  obj[prop] = {};
};
parts.forEach(function(part) {
  addNestedProp(obj, part);
}, this);

console.log(obj);


/*
result wanted:
var a = {
  b: {
    c: {
      d: {}
    }
  }
};

or:
var result = {
  a: {
    b: {
      c: {
        d: {}
      }
    }
  }
}*/
Radex
  • 7,815
  • 23
  • 54
  • 86
  • 1
    Possible duplicate of [Convert JavaScript string in dot notation into an object reference](https://stackoverflow.com/questions/6393943/convert-javascript-string-in-dot-notation-into-an-object-reference) – CBroe Jun 14 '17 at 08:57

4 Answers4

1

You could use a temporary variable to store the last created object.

It starts with a reference to obj and take the the nested object, until all parts are assigned.

var options = 'a.b.c.d',
    parts = options.split('.'),
    obj = { a: { foo: 42 } },
    temp = obj,
    addNestedProp = function(obj, prop) {
        return obj[prop] = obj[prop] || {}; // assign and return the new object,
    };                                      // but keep object if exists

parts.forEach(function(part) {
    temp = addNestedProp(temp, part);
});

console.log(obj);

While returning a new reference for each iteration, you could use Array#reduce, because it is made to return a single value, without using an addition global variable.

var options = 'a.b.c.d',
    parts = options.split('.'),
    obj = { a: { foo: 42 } };

parts.reduce(function(o, part) {
    return o[part] = o[part] || {}; // respect given object
}, obj);

console.log(obj);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

This is an example solution for your problem. Please note that I used reduce which is not supported by all browsers. You can use babel or polyfill which is described here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

var options = 'a.b.c.d';
var parts = options.split('.');
var obj = {};
var result;
parts.reduce((part, i) => part[i] = {}, obj);

result = obj;
console.log(result);

/*
result wanted:
var result = {
  a: {
    b: {
      c: {
        d: {}
      }
    }
  }
}*/
1

Short solution using Array.prototype.reduce() function:

var options = 'a.b.c.d',
    result = {};
    
options.split('.').reduce(function(r, a){
    return (r[a] = {});
}, result);

console.log(result);
Tigger
  • 8,980
  • 5
  • 36
  • 40
RomanPerekhrest
  • 88,541
  • 4
  • 65
  • 105
0

Your code is adding the properties to the same original object. You need to change the object to which the property is added (see code below).

var options = 'a.b.c.d';
var parts = options.split('.');
var obj = {};
var objorig = obj;
var addNestedProp = function(obj, prop) {
  obj[prop] = {};
};
parts.forEach(function(part) {
  addNestedProp(obj, part);
  obj = obj[part];
}, this);

console.log(objorig);


/*
result wanted:
var a = {
  b: {
    c: {
      d: {}
    }
  }
};

or:
var result = {
  a: {
    b: {
      c: {
        d: {}
      }
    }
  }
}*/
airos
  • 742
  • 5
  • 14