I was trying to normalize a very deeply nested JSON which contains all possible ways JSON can be created. A part of JSON can be seen in below code snippet.
What is my end goal
I am converting the nested JSON into a simple JS object like below
{
key1: value,
key2: value,
...
}
Problem i faced with the below solution is that when it comes to Objects with values as array
i failed to find a way to see its key values.
if you run below code
key4,key5, key6 wont get displayed with the console.log only its value gets printed.
key1 -- values
key2 -- values
key3 -- value3
0 --
0 -- some_value
Code snippet
const req = {
request: {
results: {
key1: 'values',
results: [
{
key2: 'values',
},
],
},
params: {
key3: 'value3',
query: {
key4: [''],
key5: ['123456'],
key6: ['some_value'],
},
},
},
};
function normaliseJSON(obj) {
for (let k in obj) {
if (obj[k] instanceof Object) {
normaliseJSON(obj[k]);
} else {
console.log(`${k} -- ${obj[k]}`);
}
}
}
normaliseJSON(req);
Is there any way to get the keys of key4,5,6 ? also open to any other solution to normalise such JSON
CodePudding user response:
- The reason your recursion goes inside the array is since
['123456'] instanceof Object
istrue
in javascript (typeof(['asd'])
also gives"object"
). To check if something is an array have to check withArray.isArray(something)
- In template literals when you try to embed an array eg
...${['123456']}
in the end it will show as...123456
without the brackets. Therefore in situation of Arrays need toJSON.stringify(arr)
There may be better ways of doing this but I created a function called arrayHasObject
which checks if an array has object elements. This was to catch the inner results
array and ignore key4
,key5
and key6
.
The recursion will happen if obj[k]
is an object and not an array or if obj[k]
is an array and it has an object element.
Since recursion is hard to visualize I recommend https://pythontutor.com/ . It is mostly for Python but works for JS as well. It can help you visualize these things and to find where things go wrong
Ofcourse the way I have written it will break if something like key4: [{a:'abc'}]
since arrayHasObject
gives true
for this. Maybe will need to change the function accordingly.
function arrayHasObject(arr) {
return arr.some((x) => typeof(x)==='object' && !Array.isArray(x))
}
const req = {
request: {
results: {
key1: 'values',
results: [
{
key2: 'values',
},
],
},
params: {
key3: 'value3',
query: {
key4: [''],
key5: ['123456'],
key6: ['some_value'],
},
},
},
};
function normaliseJSON(obj) {
for (let k in obj) {
if ((obj[k] instanceof Object && !Array.isArray(obj[k])) || (Array.isArray(obj[k]) && arrayHasObject(obj[k]))) {
normaliseJSON(obj[k]);
} else {
if (Array.isArray(obj[k])){
console.log(`${k} -- ${JSON.stringify(obj[k])}`);
}
else{
console.log(`${k} -- ${obj[k]}`);
}
}
}
}
normaliseJSON(req);