2

I have got a . (dot) separated string, from which I want to create nested JSON object. The length of the string is not fixed. For example,

var string = 'a.b.c.d';

Then my JSON object should be as following:

a: {
    b: {
        c:{
           d: {
                  //Some properties here. 
              }
          } 
    }
}

I've tried following code:

var packageName = "a.b.c.d"
var splitted = packageName.split('.');
var json = {};
for(var i=0;i<splitted.length-1;i++){
    json[splitted[i]] = splitted[i+1];
}

But this returns

{
    a: 'b', 
    b: 'c',
    c: 'd'
}

But this is not what I want. I've also searched on google and found similar questions, but no solutions answer my problem. For example this.

Kaushal28
  • 5,377
  • 5
  • 41
  • 72
  • You're asking how to create a nested JS object, not JSON. To create JSON would be to create your JS object, and then serialize it to the JSON text format. –  Mar 09 '18 at 16:55

3 Answers3

3

A good use case for reduce

packageName = "a.b.c.d";
initProps = {hi: 'there'};

obj = packageName.split('.').reduceRight((o, x) => ({[x]: o}), initProps);

console.log(JSON.stringify(obj))

If you find loops easier to work with, a loop could be written concisely as

result = {};
ptr = result;

for (let prop of packageName.split('.'))
    ptr = ptr[prop] = {};
georg
  • 211,518
  • 52
  • 313
  • 390
  • Thanks for alternative. But it's quite difficult for me to understand this. +1. – Kaushal28 Mar 09 '18 at 17:00
  • Excellent use case for `reduce[Right]`. So many nasty and incomprehensible examples of functional programming get posted here, especially with `reduce`, it's nice to see clean, clear, idiomatic examples. –  Mar 09 '18 at 17:01
1

You need to create a new object each time and attribute it to the last object created. And it goes until splitted.length, not splitted.length - 1, because you're using <, not <=.

var packageName = "a.b.c.d";
var splitted = packageName.split('.');
var json = {};
var current = json;
for (var i = 0; i < splitted.length; i++) {
    current[splitted[i]] = {};
    current = current[splitted[i]];
}
console.log(json);
rafaelgomesxyz
  • 1,405
  • 8
  • 14
0

You may use the last splittted part as property for some payload.

I suggest to keep the object reference and use a temporary variable for aceessing an creating a new property, if necessary.

Please avoid the use of JSON for not stringified objects.

var packageName = "a.b.c.d",
    splitted = packageName.split('.'),
    result = {},
    temp = result,
    i;
  
for (i = 0; i < splitted.length - 1; i++) {
   temp[splitted[i]] = temp[splitted[i]] || {};
   temp = temp[splitted[i]];
}

temp[splitted[i]] = { some: 'data' };

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