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)

7
  • json is malformatted Commented Apr 6, 2019 at 0: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 Commented Apr 6, 2019 at 0:31
  • Seems like this is a duplicate. See 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. Commented Apr 6, 2019 at 0: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. Commented Apr 6, 2019 at 0:45
  • 1
    Yes, I have to do it on my own, cannot use the flat module. Thanks for suggestion. Commented Apr 6, 2019 at 1:09

1 Answer 1

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);

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.