0

I am trying to flatten multi level JSON object to simple output.

key2:{  
   keyB1:{  
      keyC1:{  
         keyD1:'value b c 1'
      }
   },
   keyB2:{  
      keyC2:'value b c 2'
   }
}

My output is fine in the first iteration, but the second time, the counter is not getting set. Kindly, run the code to see the problem.

function flattenInput(datainput) {
    const result = {};

    const callit1 = function(keylist, datainput) {
        for (i in datainput) {
            keylist = keylist + '.' + i;
            if (typeof datainput[i] === 'object') {
                return callit1(keylist, datainput[i]);
            } else {
                return keylist;
            }
        }
    }

    let klist = '';
    for (i in datainput) {
        if (typeof datainput[i] === 'object') {
            klist = callit1(i, datainput[i]);
            console.log(klist);
        }
    }
    console.log(result);
}

flattenInput(input);

Expected:

key2.keyB1.keyC1.keyD1: 'value b c 1'

key2.keyB2.keyC2: 'value b c 2'

What I get:

key2.keyB1.keyC1.keyD1: 'value b c 1' (only)

Community
  • 1
  • 1
Anu Jos
  • 3
  • 2
  • json is malformatted – jonathan Heindl Apr 06 '19 at 00:30
  • I think using let i instead of jsut i should do the trick otherwise they are using the same variable probably interfering with each other – jonathan Heindl Apr 06 '19 at 00:31
  • Seems like this is a duplicate. See [fastest-way-to-flatten-un-flatten-nested-json-objects](https://stackoverflow.com/questions/19098797/fastest-way-to-flatten-un-flatten-nested-json-objects). You can pick one of solutions and adapt it to get the exact format you fancy. – Marcus Apr 06 '19 at 00:45
  • You increase the "keylist" each iteration in the callit1. The current code would give `key2.keyB1.keyB2.keyC2` for the second key. You need a different variable to store the "keylist" for the actual item or do `callit1(keylist + "." + i, datainput[i])` instead of overriding the original value. Otherwise the code looks ok. I guess it is part of an untested spaghetti code. I would check the console for errors. – inf3rno Apr 06 '19 at 00:45
  • Is this something you're trying to figure out on your own or can you just use the flat npm module? – nullforce Apr 06 '19 at 01:03
  • Added jsfiddle: https://jsfiddle.net/mhqtxv9k/ – Anu Jos Apr 06 '19 at 01:07
  • 1
    Yes, I have to do it on my own, cannot use the flat module. Thanks for suggestion. – Anu Jos Apr 06 '19 at 01:09

1 Answers1

1

You can use recursion in order to go deeper thru the keys, and an array of keys for keeping the track of visited keys.

This is assuming the deepest object is a string.

let obj = {   key2: {     keyB1: {       keyC1: {         keyD1: 'value b c 1'       }     },     keyB2: {       keyC2: 'value b c 2'     }   } };

function downstream(desiredObj, currentObj, keys) {
  if (typeof currentObj === 'string') {
    desiredObj[keys.join('.')] = currentObj;
  } else {
    Object.keys(currentObj).forEach(key => downstream(desiredObj, currentObj[key], [...keys, key]));
  }
}

let result = {};
Object.keys(obj).forEach(key => downstream(result, obj[key], [key]));

console.log(result);
Ele
  • 33,468
  • 7
  • 37
  • 75