如何扁平化JSON树并自动生成父节点,保留父子关系?
树形结构转扁平结构(带父节点关联)
这需求太常见了!我给你两种靠谱的实现方式,都是基于JavaScript的,你可以根据自己的场景选:
方法一:递归实现(简洁直观)
递归是处理树形结构最直观的方式,思路就是遍历每个节点,记录它的父节点ID,然后递归处理它的子节点。
代码示例
function flattenTree(tree) { const result = []; // 定义递归函数,处理子节点数组和对应的父ID function traverse(children, parentId) { children.forEach(node => { // 加入当前节点(只保留id和parent) result.push({ id: node.id, parent: parentId }); // 递归处理子节点,父ID就是当前节点的id if (node.children && node.children.length > 0) { traverse(node.children, node.id); } }); } // 初始调用:根节点的子节点,父ID为null traverse(tree.children, null); return result; } // 测试你的树形数据 const tree = { id: null, children: [ { id: 1, children: [ { id: 11, children: [ { id: 111, children: [] } ] }, { id: '12', children: [] } ] }, { id: '2', children: [ { id: '21', children: [] }, { id: '22', children: [ { id: '221', children: [] } ] } ] } ] }; console.log(flattenTree(tree));
说明
- 优点:代码简洁,逻辑容易理解,适合大部分常规深度的树形结构。
- 注意:如果你的树深度特别大(比如超过1000层),递归可能会触发栈溢出,这时候建议用下面的迭代方法。
方法二:迭代实现(无栈溢出风险)
用栈(或者队列)来模拟递归过程,避免递归栈的限制,适合处理超大树形结构。
代码示例
function flattenTreeIterative(tree) { const result = []; // 栈元素:[当前节点, 父节点ID] const stack = tree.children.map(node => [node, null]); while (stack.length > 0) { const [currentNode, parentId] = stack.pop(); // 加入当前节点 result.push({ id: currentNode.id, parent: parentId }); // 把子节点推入栈(注意顺序:如果要保持原顺序,需要反向推入,因为栈是后进先出) if (currentNode.children && currentNode.children.length > 0) { // 反向遍历子节点,保证弹出顺序和原顺序一致 for (let i = currentNode.children.length - 1; i >= 0; i--) { stack.push([currentNode.children[i], currentNode.id]); } } } return result; } // 测试同样的树形数据 console.log(flattenTreeIterative(tree));
说明
- 优点:完全避免递归栈溢出问题,性能更稳定,适合处理深度极大的树。
- 注意:栈是后进先出的结构,如果需要保持子节点的遍历顺序和原树一致,要反向推入栈(比如原顺序是11、12,反向推入12、11,弹出的时候就是11、12)。
两种方法最终输出的结果都和你想要的结构完全一致,你可以直接拿去用~
内容的提问来源于stack exchange,提问作者nline BGO
相关产品推荐
相关产品推荐

