I have a JSON Tree structure like this.
[
{
"title": "Blogs",
"id": "blogs",
"type": "array",
"children": [
{
"title": "Today",
"id": "today",
"type": "string"
},
{
"title": "Yesterday",
"id": "yesterday",
"type": "enum",
"options": [
"Y1",
"Y2"
]
}
]
},
{
"title": "Links",
"id": "links",
"type": "object",
"children": [
{
"title": "Oracle",
"id": "oracle",
"children": [
{
"title": "USA",
"id": "usa",
"type": "array",
"children": [
{
"title": "Midwest",
"id": "midwest",
"type": "enum",
"options": [
"Md1",
"Md2"
]
},
{
"title": "West",
"id": "west",
"type": "boolean"
}
]
},
{
"title": "Asia",
"id": "asia",
"type": "array",
"children": [
{
"title": "India",
"id": "india",
"type": "string"
}
]
}
]
}
]
}
]
I want a recursive function which takes 2 arguments(1st argument is The actual Tree Data and 2nd argument is a path with dot notation) and returns the type of the node (string/object/array/boolean) and enum values if the type is enum. The dot notation path may contain the array index as 0 or 1 or so on. Basically what i want is
var nodeType = getType(treeData, 'links.oracle.usa.0.midwest'); // Note: there is a 0 as usa is an array type
console.log(nodeType); // Should return [{"type":"enum"},{"options": ["md1", "md2"]}]
var nodeType = getType(treeData, 'blogs.0.today');
console.log(nodeType); // Should return [{"type":"string"}]
Seems like working code, which handles wrong paths as well:
const sample = [
{
"title": "Blogs",
"id": "blogs",
"type": "array",
"children": [
{
"title": "Today",
"id": "today",
"type": "string"
},
{
"title": "Yesterday",
"id": "yesterday",
"type": "enum",
"options": [
"Y1",
"Y2"
]
}
]
},
{
"title": "Links",
"id": "links",
"type": "object",
"children": [
{
"title": "Oracle",
"id": "oracle",
"children": [
{
"title": "USA",
"id": "usa",
"type": "array",
"children": [
{
"title": "Midwest",
"id": "midwest",
"type": "enum",
"options": [
"Md1",
"Md2"
]
},
{
"title": "West",
"id": "west",
"type": "boolean"
}
]
},
{
"title": "Asia",
"id": "asia",
"type": "array",
"children": [
{
"title": "India",
"id": "india",
"type": "string"
}
]
}
]
}
]
}
]
const getType = (tree, path) => {
if (!path.length) return
const element = getElementFromTree(tree, path.split('.'))
if (!element || !element.type) return
const res = [{ type: element.type }]
if (element.options) {
res.push({ options: element.options })
}
return res
}
const getElementFromTree = (treePart, path) => {
const prop = path.shift()
if (!path.length) {
return treePart.id === prop ? treePart : undefined
}
let nextTreePart;
if (Array.isArray(treePart)) {
nextTreePart = treePart.find(v => v.id === prop)
} else if (isNaN(prop)) {
nextTreePart = treePart.children.find(v => v.id === prop)
} else {
nextTreePart = treePart.children[prop]
}
if (!nextTreePart) return
if (path.length) {
return getElementFromTree(nextTreePart, path)
}
return nextTreePart
}
// work as expected:
console.log(getType(sample, 'links.oracle.usa.0.midwest'))
console.log(getType(sample, 'links.oracle.usa.1.west'))
console.log(getType(sample, 'blogs.0.today'))
console.log(getType(sample, 'blogs.1.yesterday'))
console.log(getType(sample, 'links.oracle.asia.0.india'))
// tests with wrong paths, all return undefined
console.log(getType(sample, 'links.oracle.usa.5.west')) // because 5th element doesn't exists
console.log(getType(sample, 'blogs.3.today')) // because 3rd element doesn't exists
console.log(getType(sample, 'links.oracle')) // because links.oracle doesn't contain type field in it
console.log(getType(sample, '10.this.is.wrong.path')) // because path doesn't exist at all