You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将扁平JSON转换为带subNav层级结构?现有代码存在嵌套问题

扁平JSON数组转层级化导航结构的实现方案

需求说明

我有一个扁平结构的JSON数组:

const content = [
  { title: "Item 1", metaData: { "level": 1, "desc": "Some Desc 1", "displayOnOverview": true }},
  { title: "Item 2", metaData: { "level": 2, "desc": "Some Desc 2", "displayOnOverview": true }},
  { title: "Item 3", metaData: { "level": 2, "desc": "Some Desc 3", "displayOnOverview": false }},
  { title: "Item 4", metaData: { "level": 3, "desc": "Some Desc 4", "displayOnOverview": true }},
  { title: "Item 5", metaData: { "level": 1, "desc": "Some Desc 5", "displayOnOverview": true }}
];

需要将其转换为带subNav子层级的嵌套结构:

[
  {
    "title": "Item 1",
    "metaData": {
      "desc": "Some Desc 1",
      "displayOnOverview": true
    },
    "subNav": [
      {
        "title": "Item 2",
        "metaData": {
          "desc": "Some Desc 2",
          "displayOnOverview": true
        }
      },
      {
        "title": "Item 3",
        "metaData": {
          "desc": "Some Desc 3",
          "displayOnOverview": false
        },
        "subNav": [
          {
            "title": "Item 4",
            "metaData": {
              "desc": "Some Desc 4",
              "displayOnOverview": true
            }
          }
        ]
      }
    ]
  },
  {
    "title": "Item 5",
    "metaData": {
      "desc": "Some Desc 5",
      "displayOnOverview": true
    }
  }
]

现有代码的问题

我写的代码只能处理顶层节点,遇到Item 3这类同级节点时就失效了:

// Create root for top-level node(s)
const root = [];

sideNavData.forEach((node, index) => {
    const nodeLevel = node.metaData.level;

    if (root.length === 0) {
        return root.push(node)
    }

    const previousLevel = root[index - 1].metaData.level;

    if (previousLevel === nodeLevel) {
        return root.push(node)
    } else {
        return root[index - 1]['subNav'] = node
    }
});

console.log(root);

核心问题:

  • 仅跟踪根数组的前一个元素,未考虑深层嵌套的父节点
  • 直接将子节点赋值为单个对象,而非数组,无法支持多个同级子节点
  • 未处理层级跨级跳转的场景(比如从level3回到level1)

实现思路

解决这类层级转换问题的核心是维护一个层级栈,通过栈记录当前各层级的父节点,快速定位当前节点的归属:

  1. 初始化根结果数组和层级栈,栈中每个元素保存节点实例及其对应的层级
  2. 遍历每个扁平节点:
    • 复制当前节点并移除metaData中的level字段(目标结构不需要该字段)
    • 根据当前节点的层级,调整栈的长度:弹出栈中所有层级大于等于当前层级的元素,直到找到层级比当前小1的父节点
    • 若当前层级为1,直接加入根数组并推入栈;若为子节点,找到栈顶父节点,确保subNav数组存在后将当前节点加入,再推入栈

完整实现代码

const content = [
  { title: "Item 1", metaData: { "level": 1, "desc": "Some Desc 1", "displayOnOverview": true }},
  { title: "Item 2", metaData: { "level": 2, "desc": "Some Desc 2", "displayOnOverview": true }},
  { title: "Item 3", metaData: { "level": 2, "desc": "Some Desc 3", "displayOnOverview": false }},
  { title: "Item 4", metaData: { "level": 3, "desc": "Some Desc 4", "displayOnOverview": true }},
  { title: "Item 5", metaData: { "level": 1, "desc": "Some Desc 5", "displayOnOverview": true }}
];

function flattenToNested(data) {
  const result = [];
  const stack = [];

  data.forEach(item => {
    // 复制节点并移除metaData中的level字段
    const node = {
      title: item.title,
      metaData: { ...item.metaData }
    };
    delete node.metaData.level;

    const currentLevel = item.metaData.level;

    // 调整栈:弹出所有层级 >= 当前层级的节点,找到父节点
    while (stack.length > 0 && stack[stack.length - 1].level >= currentLevel) {
      stack.pop();
    }

    if (currentLevel === 1) {
      result.push(node);
    } else {
      // 获取父节点,确保subNav存在
      const parent = stack[stack.length - 1].node;
      if (!parent.subNav) {
        parent.subNav = [];
      }
      parent.subNav.push(node);
    }

    // 将当前节点和层级推入栈
    stack.push({ node, level: currentLevel });
  });

  return result;
}

const nestedNav = flattenToNested(content);
console.log(JSON.stringify(nestedNav, null, 2));

内容的提问来源于stack exchange,提问作者ReynierPM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 23:35:38