如何基于group属性将JSON对象转换为层级嵌套结构?
问题:将带group属性的JSON转换为嵌套层级结构
我有如下JSON对象:
{"id": "jsonid","attributes": {"personName": {"id": "name1","group": "1.1"},"age": {"id": "age1","group": "1.2.1"},"height": {"id": "height1","group": "1.2.2.1"}}}
其中group属性的值表示该属性在层级树中从根节点到最终节点的位置,需要转换为如下嵌套结构的JSON:
{"id": "jsonid","attributes": {"group1": {"id": "group1","attributes": {"group1.1": {"id": "group1.1","attributes": {"personName": {"id": "name1"}}},"group1.2": {"id": "group1.2","attributes": {"group1.2.1": {"id": "group1.2.1","attributes": {"age": {"id": "age1"}}},"group1.2.2": {"id": "group1.2.2","attributes": {"group1.2.2.1": {"id": "group1.2.2.1","attributes": {"height": {"id": "height1"}}}}}}}}}
我已经生成了所有唯一group的可能组合:["1", "1.1", "1.2", "1.2.1", "1.2.2", "1.2.2.1"],并编写了如下迭代逻辑和createGroups函数,但无法正确实现转换,请求完善该函数。
当前迭代逻辑
allPossible.map((groupId, index, array) => { createGroups(groupId, index, array); });
当前createGroups函数
const createGroups = (groupId, index, array) => { let groupObject = { [groupId]: { id: groupId, attributes: {}, }, }; if (array[index + 1]) { //If next element exists if (groupId.length === array[index + 1].length) { //To Check if the element should be in the same level //e.g. group ids 1.1 and 1.2 should be under group id 1 let groupIdPrevious = array[index - 1]; groupObject[groupIdPrevious].attributes = createGroups( array[index + 1], index + 1, array ); } groupObject[groupId].attributes = createGroups( array[index + 1], index + 1, array ); } return groupObject; };
解决方案
你的当前思路存在两个核心问题:一是通过字符串长度判断同级节点不准确(比如"1.10"和"1.2"长度不同但属于同级);二是递归逻辑未正确定位父节点,直接将下一个节点挂载到当前节点下,导致层级混乱。
下面是修正后的完整实现,分两步构建目标结构:先搭建完整的group层级树,再将原始属性挂载到对应叶子group节点。
1. 构建group层级结构
function buildGroupHierarchy(groupPaths) { const root = {}; groupPaths.forEach(path => { const segments = path.split('.'); let current = root; let currentPath = ''; segments.forEach((seg, idx) => { currentPath = idx === 0 ? seg : `${currentPath}.${seg}`; const groupKey = `group${currentPath}`; // 匹配目标结构的group前缀规则 if (!current[groupKey]) { current[groupKey] = { id: groupKey, attributes: {} }; } current = current[groupKey].attributes; }); }); return root; }
2. 挂载原始属性到对应group节点
function attachAttributes(groupHierarchy, originalAttributes) { Object.entries(originalAttributes).forEach(([attrName, attrData]) => { const groupPath = attrData.group; const segments = groupPath.split('.'); let current = groupHierarchy; let currentPath = ''; segments.forEach((seg, idx) => { currentPath = currentPath ? `${currentPath}.${seg}` : seg; const groupKey = `group${currentPath}`; if (idx === segments.length - 1) { // 到达目标group节点,挂载属性 current[groupKey].attributes[attrName] = { id: attrData.id }; } else { current = current[groupKey].attributes; } }); }); }
3. 完整转换函数
function transformJson(originalJson) { const { id, attributes: originalAttrs } = originalJson; // 提取所有group路径并去重 const allGroups = [...new Set(Object.values(originalAttrs).map(attr => attr.group))]; // 自动补充所有父级group路径(比如从"1.1"生成"1") const allPossibleGroups = new Set(); allGroups.forEach(path => { const segments = path.split('.'); let currentPath = ''; segments.forEach(seg => { currentPath = currentPath ? `${currentPath}.${seg}` : seg; allPossibleGroups.add(currentPath); }); }); // 排序确保父节点在子节点前处理 const sortedGroups = Array.from(allPossibleGroups).sort(); // 构建层级并挂载属性 const groupHierarchy = buildGroupHierarchy(sortedGroups); attachAttributes(groupHierarchy, originalAttrs); return { id: id, attributes: groupHierarchy }; }
使用示例
const original = {"id": "jsonid","attributes": {"personName": {"id": "name1","group": "1.1"},"age": {"id": "age1","group": "1.2.1"},"height": {"id": "height1","group": "1.2.2.1"}}}; const result = transformJson(original); console.log(JSON.stringify(result, null, 2));
这段代码的核心逻辑是:
- 通过拆分group路径的片段,逐层创建group节点,确保父节点优先于子节点被创建
- 遍历原始属性,根据其group路径精准定位到目标group节点,完成属性挂载
- 自动补充所有缺失的父级group节点,无需手动提前生成完整的group列表
内容的提问来源于stack exchange,提问作者Coder
相关产品推荐
相关产品推荐

