将点表示法键的对象转换为适配treeselect的树形嵌套JSON
将点表示法键的JS对象转换为适配jquery.treeselect.js的树形结构
需求说明
需要把键采用点表示法的JavaScript对象,转换为包含id、title、has_children、level、value、children字段的层级嵌套结构,用于适配jquery.treeselect.js插件。
示例输入
const obj = { "project1.foo.a": "value", "project1.foo.b": "value", "project1.bar": "value", "project2.foo.a": "value", "project2.foo.b": "value", "project2.foo.c": "value", "project2.foo.bar": "value" };
当前问题
使用lodash实现的unflatten函数仅能还原扁平化对象,但无法递归生成符合插件要求的、包含指定字段的children嵌套结构:
const unflatten = (flattedObject) => { let result = {}; _.keys(flattedObject).forEach(function (key) { _.set(result, key, flattedObject[key]); }) return result; } console.log(unflatten(obj));
实现方案
下面的代码会先构建节点映射,再递归生成符合要求的树形结构:
function convertToTreeselectStructure(flatObj) { // 节点映射表,用于快速查找和创建节点 const nodeMap = new Map(); const rootNodes = []; // 遍历所有键值对,拆分路径并构建节点 Object.entries(flatObj).forEach(([key, value]) => { const pathSegments = key.split('.'); let parentNode = null; pathSegments.forEach((segment, index) => { const nodeId = pathSegments.slice(0, index + 1).join('.'); let node = nodeMap.get(nodeId); if (!node) { // 创建新节点 node = { id: nodeId, title: segment, has_children: index !== pathSegments.length - 1, // 非最后一段则有子节点 level: index, value: index === pathSegments.length - 1 ? value : undefined, // 仅叶子节点赋值 children: [] }; nodeMap.set(nodeId, node); // 关联父节点或加入根节点列表 if (index === 0) { rootNodes.push(node); } else { parentNode.children.push(node); } } parentNode = node; }); }); return rootNodes; } // 测试使用 const obj = { "project1.foo.a": "value", "project1.foo.b": "value", "project1.bar": "value", "project2.foo.a": "value", "project2.foo.b": "value", "project2.foo.c": "value", "project2.foo.bar": "value" }; const treeStructure = convertToTreeselectStructure(obj); console.log(JSON.stringify(treeStructure, null, 2));
代码说明
- 节点映射表:用
Map存储每个节点的完整路径ID与节点对象的映射,避免重复创建节点。 - 路径拆分:将每个点表示法的键拆分为路径数组,逐个层级创建节点。
- 节点字段设置:
id:当前节点的完整路径,作为唯一标识title:当前路径段的名称(如project1、foo)has_children:判断当前节点是否为叶子节点,非路径最后一段则为truelevel:当前节点的层级,从0开始计数value:仅叶子节点赋值为原对象对应的值,非叶子节点设为undefinedchildren:存储子节点的数组
- 父子关联:每个非根节点创建后,会被添加到其父节点的
children数组中。
输出示例(简化版)
[ { "id": "project1", "title": "project1", "has_children": true, "level": 0, "value": undefined, "children": [ { "id": "project1.foo", "title": "foo", "has_children": true, "level": 1, "value": undefined, "children": [ { "id": "project1.foo.a", "title": "a", "has_children": false, "level": 2, "value": "value", "children": [] } ] } ] } ]
内容的提问来源于stack exchange,提问作者Xyz753
相关产品推荐
相关产品推荐

