I have a javascript dictionary:
{
"a": {
"b": {
"c": null,
"d": null
}
}
}
How can I turn it into a JSON object which I can specify the name and children property? Is there any elegant way to do it? The JSON object could be:
{
name:"a"
children: [{
name:"b",
children: [{
name:"c",
children: null
},{
name:"d",
children: null}]
}]
}
I have a javascript dictionary:
{
"a": {
"b": {
"c": null,
"d": null
}
}
}
How can I turn it into a JSON object which I can specify the name and children property? Is there any elegant way to do it? The JSON object could be:
{
name:"a"
children: [{
name:"b",
children: [{
name:"c",
children: null
},{
name:"d",
children: null}]
}]
}
You could create a recursive function for generating your output:
var x = {
"a": {
"b": {
"c": null,
"d": null
}
}
};
function generate(item, key) {
var result = {
name: key,
children: []
};
for (var _ in item)
result.children.push(generate(item[_], _))
if (result.children.length == 0)
result.children = null;
return (key == undefined) ? result.children : result;
}
console.log(JSON.stringify(generate(x), null, 1));
Output:
[
{
"name": "a",
"children": [
{
"name": "b",
"children": [
{
"name": "c",
"children": null
},
{
"name": "d",
"children": null
}
]
}
]
}
]
The above generate
function returns a list instead of a dictionary, because it's possible to have more than one name at the root level. But if we are sure that we have only one name at the root name, we can generate the json like this:
console.log(JSON.stringify(generate(x)[0], null, 1));
Here's my solution. It's similar to JuniorCompressor's.
function generate(obj) {
// Return primitives as-is
if (!(obj instanceof Object)) return obj;
// Loop through object properties and generate array
var result = [];
for (var key in obj) {
result.push({
name: key,
children: generate(obj[key])
});
}
// Return resulting array
return result;
}
As mentioned, the resulting object will actually be an array (in case there is more than one root-level property in the original object). If you really need the resulting object to be an object with only properties name and value, then you should access the first element of the resulting array, like this:
generate(obj)[0]
You need a recursive function, which calls itself for children. Note that in your example, there is only one top-level child (a). I instead use the assumption that the top-level 'name' refers to the name of the actual object itself. If you want to get results exactly like you demonstrate, from an object called 'obj', run toJSON(obj).children[0]. For the overall function, try something like the following:
function toJSON(obj, name) {
var subTree = {
name: name,
children: []
};
if (obj !== null && Object.keys(obj).length >= 1) {
for (var child in obj) {
subTree.children.push(toJSON(obj[child], child));
}
} else {
subTree.children = null;
}
return subTree;
}
Results of toJSON(obj).children[0]:
{
"name": "a",
"children": [{
"name": "b",
"children": [{
"name": "c",
"children": null
},{
"name": "d",
"children": null
}]
}]
}
Results of toJSON(obj, 'obj'):
{
"name": "obj",
"children": [{
"name": "a",
"children": [{
"name": "b",
"children": [{
"name": "c",
"children":null
},
{
"name": "d",
"children": null
}]
}]
}]
}
Here's a line-by-line explanation:
The original function only used one argument, whereas that above has another argument for 'name'. This is because the original tried to figure out the name of each level within that same level, which I have since realized isn't possible in Javascript. Basically, the original didn't work, and an extra argument had to be added to make it work. For records' sake, though, here was the original function:
// THIS FUNCTION DOESN'T WORK. IT'S HERE ONLY FOR HISTORICAL ACCURACY:
function toJSON(obj) {
var subTree = {
name: obj.constructor.name, // This should get the object key
children: []
};
if (Object.keys(obj).length >= 1) { // If there is at least one child
for (var child in obj) {
subTree.children.push(toJSON(obj[child]));
}
} else {
subTree.children = null;
}
return subTree;
}