Reputation: 12034
I'm trying to use a recursive function to get the last key value form a simple json
using javascript
I have this json
:
{
'a': {
'b': {
'c': 12,
'd': 'Hello World'
},
'e': [1,2,3]
}
}
And my expected result is:
{
'a/b/c': 12,
'a/b/d': 'Hello World',
'a/e': [1,2,3]
}
I'm trying with:
function getDeepKeys(obj) {
var keys = [];
for (var key in obj) {
keys.push(key);
if (typeof obj[key] === "object") {
var subkeys = getDeepKeys(obj[key]);
keys = keys.concat(subkeys.map(function (subkey) {
return key + "/" + subkey;
}));
}
}
return keys;
}
But for some reason, it returns me:
a/b/c/d/e/0/1/
, I'm not sure why it is adding those numbers there.
Someone has an idea about how I can do it?
Upvotes: 2
Views: 232
Reputation: 57175
You can do it iteratively with an explicit stack which has less overhead than recursion and won't blow the call stack:
const pathify = o => {
const paths = {};
const stack = [[o, []]];
while (stack.length) {
const [curr, path] = stack.pop();
for (const k in curr) {
if (typeof curr[k] === "object" && !Array.isArray(curr[k])) {
stack.push([curr[k], path.concat(k)]);
}
else {
paths[`${path.join("/")}/${k}`] = curr[k];
}
}
}
return paths;
};
console.log(pathify({'a':{'b':{'c':12,'d':'Hello World'},'e':[1,2,3]}}));
Upvotes: 4
Reputation: 92460
I think you may be making it more complicated than necessary. You can test for an array with Array.isArray
and an non-object (typeof !== 'object
) and just return the path and value. Otherwise recurse for each entry. reduce()
is good for that. Passing the current path as an argument to the recursive function is convenient too:
let obj = {'a': {'b': {'c': 12,'d': 'Hello World'},'e': [1,2,3]}}
function getValues(obj, path = []){
return (Array.isArray(obj) || typeof obj !== 'object')
? {[path.join('/')]: obj}
: Object.entries(obj).reduce((acc, [key, val]) =>
Object.assign(acc, getValues(val, path.concat(key)) )
, {})
}
console.log(getValues(obj))
Upvotes: 3
Reputation: 33726
You can use the function Object.keys
to loop the keys of the objects and with recursion, you can go deeper through the nested objects.
let obj = {'a': {'b': {'c': 12,'d': 'Hello World'},'e': [1,2,3]}},
result = Object.create(null),
loop = function (o, arr, result) {
Object.keys(o).forEach(k => {
arr.push(k);
if (typeof o[k] === 'object' && !Array.isArray(o[k])) loop(o[k], arr, result);
else result[arr.join('/')] = o[k];
arr.splice(-1);
});
};
loop(obj, [], result);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 0