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

纯JS实现任意深度JSON重构为带name和children的树形结构

JSON结构转树形格式实现方案

两种纯JavaScript实现方式均支持任意嵌套深度的JSON结构转换,输出完全符合要求的name+children结构。

递归实现

核心逻辑是按值的类型分发处理逻辑,遇到嵌套对象/数组时递归生成子节点,代码简洁易读,适配绝大多数常规场景:

function transformToTree(input, rootName = 'data') {
  // 生成基础类型叶子节点
  const createLeafNode = (value) => ({
    name: String(value)
    // 若业务要求所有节点必须带children属性,放开下一行注释即可
    // , children: []
  })

  // 单节点递归处理逻辑
  const processNode = (key, value) => {
    const currentNode = {
      name: key,
      children: []
    }

    // 处理普通对象:遍历所有键值对递归生成子节点
    if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
      Object.entries(value).forEach(([childKey, childValue]) => {
        currentNode.children.push(processNode(childKey, childValue))
      })
      return currentNode
    }

    // 处理数组:遍历每一项,基础值生成叶子,嵌套结构继续递归
    if (Array.isArray(value)) {
      value.forEach((item, index) => {
        if (item !== null && typeof item === 'object') {
          // 数组内无明确键名的对象/数组,默认用索引作为节点name,可按业务需求调整
          currentNode.children.push(processNode(String(index), item))
        } else {
          currentNode.children.push(createLeafNode(item))
        }
      })
      return currentNode
    }

    // 处理基础类型值:挂载到当前节点的子节点列表
    currentNode.children.push(createLeafNode(value))
    return currentNode
  }

  // 初始化根节点
  const root = {
    name: rootName,
    children: []
  }
  Object.entries(input).forEach(([key, value]) => {
    root.children.push(processNode(key, value))
  })
  return root
}

// 测试调用
const rawJson = {
  "varA":true,
  "varB":false,
  "varC": {
    "time":"15:00:00",
    "date":"Jul 10",
    "items":["apple", "banana"]
  }
}
console.log(transformToTree(rawJson)) // 输出与目标结构完全一致

迭代实现

递归依赖JS引擎的函数调用栈,处理超深嵌套(比如层级过万)时可能触发栈溢出,用手动维护栈的迭代方式可以规避这个问题,逻辑和递归完全等价:

function transformToTreeIterative(input, rootName = 'data') {
  const createLeaf = (val) => ({
    name: String(val)
    // 若业务要求所有节点必须带children属性,放开下一行注释即可
    // , children: []
  })
  // 初始化根节点
  const root = { name: rootName, children: [] }
  // 手动维护处理栈,栈元素格式为[当前待挂载节点, 待处理的值]
  const stack = []

  // 根节点下的一级属性先入栈
  Object.entries(input).forEach(([key, value]) => {
    const node = { name: key, children: [] }
    root.children.push(node)
    stack.push([node, value])
  })

  while (stack.length) {
    const [currentNode, currentValue] = stack.pop()

    // 处理普通对象
    if (currentValue !== null && typeof currentValue === 'object' && !Array.isArray(currentValue)) {
      Object.entries(currentValue).forEach(([childKey, childVal]) => {
        const childNode = { name: childKey, children: [] }
        currentNode.children.push(childNode)
        stack.push([childNode, childVal])
      })
      continue
    }

    // 处理数组
    if (Array.isArray(currentValue)) {
      currentValue.forEach((item, idx) => {
        if (item !== null && typeof item === 'object') {
          const childNode = { name: String(idx), children: [] }
          currentNode.children.push(childNode)
          stack.push([childNode, item])
        } else {
          currentNode.children.push(createLeaf(item))
        }
      })
      continue
    }

    // 处理基础类型
    currentNode.children.push(createLeaf(currentValue))
  }

  return root
}

注意事项

  • 两种实现默认将布尔、数字等基础类型值转为字符串作为叶子节点的name,和示例输出规则一致
  • 数组内的嵌套对象默认用索引作为name标识,可根据业务需求调整为自定义标识规则
  • 如果要求所有节点(包括叶子节点)必须携带空children数组,放开代码中对应位置的注释即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 00:33:26