I am trying to write a javascript recursive function that receives one parameter - nested JSON object.
The function goes through the potentially infinitely nested object and converts all the keys (property names) to a string that is stored in array. Array is returned to a place where the function was called.
Example of JSON object:
{
OBJECT1: {
ATTRIBUTE3: {
PARAMETER2: {
PROPERTY1: {
}
}
}
}
}
The object does not hold any values.
What i tried and did not work:
function convertKeysToString(obj) {
let keys = [];
for (let key in obj) {
if (typeof obj[key] === 'object') {
keys = keys.concat(convertKeysToString(obj[key]));
} else {
keys.push(key.toString());
}
}
return keys;
}
As a result, I expected that returned key is pushed to an array, but the funciton didnt get the key at all or was not pushed to keys array.
Another code I tried:
function getNestedObjectKeys(obj) {
var keys = []
var firstLevel = null
var property = Object.keys(obj)
property = property[0]
firstLevel = Object.keys(obj[property])[0]
if (firstLevel == undefined) {
return 0
}
let returnedValue = keys.unshift(getNestedObjectKeys(obj[property]))
if (returnedValue == 0) {
return Object.keys(obj[property])[0]
}
returnedValue = Object.keys(obj[property])[0]
if (returnedValue != obj[property[0]]) {
return Object.keys(obj[property])[0]
}
else if (returnedValue == firstLevel) {
return keys
}
}
The function should return the key name and push (unshift) it to string and then return it, but the unshift doesnt do what I expect and in the returnedValue is not a expected returned string.
I approached it the way that the function findd the deepest (empty) object, and starts returning the name of the key. The thing is that I must return the key name AND push it to the string, which I can't find the way to accomplish at once.
CodePudding user response:
Your first solution is pretty close, but has one problem (well, one main problem): when the value is type object
, you don't add its key to the array. So how is it supposed to get into the array? Give this a shot:
function convertKeysToString(obj) {
let keys = [];
for (let key in obj) {
keys.push(key.toString());
if (typeof obj[key] === 'object') {
keys = keys.concat(convertKeysToString(obj[key]));
}
}
return keys;
}
Other things you may want to consider:
typeof null
isobject
.typeof []
is alsoobject
.
CodePudding user response:
It looks like your first approach is on the right track, but you're not correctly handling the case where the value of the key is an object. Instead of checking if the value is an object, you should check if it's an object and not an array. If it's an object, you should recursively call the function on that object. Here's an example of how you could modify your code to accomplish this:
function convertKeysToString(obj) {
let keys = [];
for (let key in obj) {
if (typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
keys = keys.concat(convertKeysToString(obj[key]));
} else {
keys.push(key.toString());
}
}
return keys;
}
For the second code, you are trying to unshift the returned value of the recursive call, but you need to push it to the keys array. Also, there is no need to check the return value of the function as you can directly push to the keys array.
function getNestedObjectKeys(obj) {
var keys = []
var property = Object.keys(obj)
property = property[0]
if (property == undefined) {
return 0
}
keys.push(property)
getNestedObjectKeys(obj[property])
return keys
}
This should work as expected and return the keys in the nested object
CodePudding user response:
You could have a look to object, which are truthy and typeof object.
const
getKeys = object => (keys => [
...keys.flatMap(key => object[key] && typeof object[key] === 'object'
? [key, ...getKeys(object[key])]
: [key]
)
])(Object.keys(object)),
data = { OBJECT1: { ATTRIBUTE3: { PARAMETER2: { PROPERTY1: {} } } } },
result = getKeys(data);
console.log(result);