I struggle with tree structure. :(
I would like to make a tree following the below interface.
export type Tree = Array<TreeNode>;
export interface TreeNode {
label: string;
type: 'folder' | 'file';
children: Array<TreeNode> | string;
}
For example,
I have a JSON file like this
{
"common.header.title": "Header Title",
"common.footer.btn": "Footer button",
"common.footer.btn.submit": "Footer Submit",
"apage.title": "apage Title"
}
My expected output is like this.
const out = [
{
label: 'apage',
type: 'folder',
children: [
{ label: 'title', type: 'file', children: 'apage Title' }
]
}, {
label: 'common',
type: 'folder',
children: [
{
label: 'footer',
type: 'folder',
children: [
{ label: 'btn', type: 'file', children: 'Footer button' },
{
label: 'btn',
type: 'folder',
children: [{ label: 'submit', type: 'file', children: 'Footer Submit' }]
},
]
}, {
label: 'header',
type: 'folder',
children: [{ label: 'title', type: 'file', children: 'Header Title' }]
}
]
}
]
I've seen some similar cases in SO, but I couldn't refer and develop with that cases.
CodePudding user response:
You could search for the wanted labels and check if children
is an array, then use this object for searchin in the nested array.
Finally push a new object.
const
data = { "common.header.title": "Header Title", "common.footer.btn": "Footer button", "common.footer.btn.submit": "Footer Submit", "apage.title": "apage Title" },
result = Object
.entries(data)
.sort(([a], [b]) => a.localeCompare(b))
.reduce((r, [path, children]) => {
const
keys = path.split('.'),
label = keys.pop();
keys
.reduce((t, label) => {
let temp = t.find(o => o.label === label && Array.isArray(o.children));
if (!temp) t.push(temp = { label, type: 'folder', children: [] });
return temp.children;
}, r)
.push({ label, type: 'file', children });
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }