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

如何将嵌套JSON对象转换为指定的数组结构?

嵌套JSON转树形结构(含parentId、path等属性)

问题背景

需要将嵌套JSON对象转换为指定的树形结构,新增key、title、parentId、id、path、isLeaf、selectable等属性:

原始JSON输入

let jsonObj = {
  "data": {
    "cardShop": {
      "cardData": {
        "cardTitle": "The Platinum Card<sup>®</sup>",
        "cardType": "credit-cards",
        "dtmProductName": "PlatinumCard",
        "viewAllCards": {
          "url": "credit-cards/all-cards",
          "text": "All Cards"
        }
      },
      "eligibilityChecker": {
        "header": "Check your eligibility",
        "subHeader": "The Platinum Card®",
        "bulletPoints": [
          "Only takes a couple of minutes to complete",
          "Will not impact your credit rating",
          "Allows you to apply with confidence"
        ]
      }
    }
  }
}

目标树形结构格式

[
  {
    id: "cardShop",
    key: "cardShop",
    title: "cardShop",
    selectable: false,
    children: [
      {
        id: "cardData",
        path: "cardShopCardData",
        key: "cardData",
        title: "cardData",
        parentId: "cardShop",
        selectable: false,
        children: [
          {
            id: "cardTitle",
            path: "cardShopcardDatacardTitle",
            key: "cardTitle",
            title: "cardTitle",
            parentId: "cardData",
            isLeaf: true,
            children: []
          },
          {
            id: "cardType",
            key: "cardType",
            title: "cardType",
            parentId: "cardData",
            isLeaf: true,
            children: []
          },
          {
            id: "dtmProductName",
            key: "dtmProductName",
            title: "dtmProductName",
            parentId: "cardData",
            isLeaf: true,
            children: []
          },
          {
            id: "viewAllCards",
            key: "viewAllCards",
            title: "viewAllCards",
            parentId: "cardData",
            selectable: false,
            children: [
              {
                id: "url",
                key: "url",
                title: "url",
                parentId: "viewAllCards",
                isLeaf: true,
              },
              {
                id: "text",
                key: "text",
                title: "text",
                parentId: "viewAllCards",
                isLeaf: true,
              }
            ]
          }
        ]
      },
      {
        id: "eligibilityChecker",
        key: "eligibilityChecker",
        title: "eligibilityChecker",
        parentId: "cardShop",
        selectable: false,
        children: [
          {
            id: "header",
            key: "header",
            title: "header",
            parentId: "eligibilityChecker",
            isLeaf: true,
            children: []
          },
          {
            id: "subHeader",
            key: "subHeader",
            title: "subHeader",
            parentId: "eligibilityChecker",
            isLeaf: true,
            children: []
          },
          {
            id: "bulletPoints",
            key: "bulletPoints",
            title: "bulletPoints",
            parentId: "eligibilityChecker",
            isLeaf: true,
            children: []
          }
        ]
      }
    ]
  }
];

尝试的代码(未得到预期结果)

let prevKey =""
const iterate = (obj) => {
  Object.keys(obj).forEach(key => {
  if (typeof obj[key] === 'object' && obj[key] !== null) {
  
    let c ={
      id:key,
      title:key,
      selelected:false,
      children:[]
    };
    if(prevKey && Object.keys(output).length === 0){
      output ={
        children :[]
      }
     output.children.push(c)
    }
    else if(prevKey ){
      output.children.push(c)

    } else{
      output = c
    }
    prevKey = key;
    iterate(obj[key])

      }
      else{
        let c ={
        id:key,
        title:key,
        selelected:false,
        children:[]
      };
      output.children[0].children.push(c)
      }
  })
}

解决方案

核心思路是递归遍历每个节点,同时传递父节点ID、当前路径前缀等上下文信息,区分叶子节点(值为非对象/数组类型)和非叶子节点(值为对象类型),为每个节点添加对应属性。

完整转换代码

// 递归转换函数
const transformToTree = (obj, parentId = '', pathPrefix = '') => {
  return Object.keys(obj).map(key => {
    const currentPath = pathPrefix ? `${pathPrefix}${key}` : key;
    const node = {
      id: key,
      key: key,
      title: key,
      parentId: parentId,
      children: []
    };

    const value = obj[key];
    // 判断是否为叶子节点:值不是对象/数组,或者是数组、null
    const isLeaf = typeof value !== 'object' || value === null || Array.isArray(value);

    if (isLeaf) {
      node.isLeaf = true;
      node.path = currentPath;
    } else {
      node.selectable = false;
      node.path = currentPath;
      // 递归处理子节点,传递当前key作为父ID、当前路径作为前缀
      node.children = transformToTree(value, key, currentPath);
    }

    return node;
  });
};

// 调用转换函数(取原始JSON的data字段内容)
const result = transformToTree(jsonObj.data);
console.log(JSON.stringify(result, null, 2));

代码说明

  1. 递归参数:obj为当前处理的对象,parentId传递父节点ID,pathPrefix用于拼接生成节点的path属性。
  2. 基础属性生成:每个节点默认生成id、key、title、parentId、children属性。
  3. 叶子节点处理:当节点值为非对象、null或数组时,标记为叶子节点(isLeaf: true),不再递归子节点。
  4. 非叶子节点处理:添加selectable: false属性,递归处理子对象并赋值给children。
  5. 路径拼接:通过父路径前缀+当前key生成节点的path属性。

内容的提问来源于stack exchange,提问作者K.S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 21:40:35