创建递归 JSON 层次结构树时出现问题

Issue in creating recursive JSON hierarchy tree

我有平面文件格式的输入数据。我已经编写了 javascript 代码来创建递归层次结构 JSON 树。我没有得到预期的树(下面突出显示为预期输出)。任何人都可以帮助我了解我可能哪里出错了吗?

注:输入数据中如果没有child_id表示是叶节点

用代码输入数据

var data=[
         {"Type":"Root","url":"abc","description":"Enterprise Risk Management Framework","id":0,"child_id":3},

{"Type":"Stem","url":"def","description":"Risk Governance Framework","id":3,"child_id":4},

{"Type":"Stem","url":"def","description":"Risk Governance Framework","id":3,"child_id":9},

{"Type":"Stem","url":"def","description":"Risk Governance Framework","id":3,"child_id":11},

{"Type":"Stem","url":"ghi","description":"Wholesale Credit Risk framework","id":4,"child_id":6},

{"Type":"Stem","url":"jkl","description":"Wholesale Credit Risk Policy","id":6,"child_id":7},

{"Type":"Stem","url":"jkl","description":"Wholesale Credit Risk Policy","id":6,"child_id":8},

{"Type":"Leaf","url":"mno","description":"Wholesale Credit In-Business Quality Assurance Standard","id":7},

{"Type":"Leaf","url":"pqr","description":"WCR Exception Management Standard","id":8},

{"Type":"Stem","url":"stu","description":"Global Collateral Management Policy","id":9,"child_id":10},

{"Type":"Leaf","url":"gov","description":"WCR Collateral Management Standard","id":10},

{"Type":"Stem","url":"iit","description":"Real Estate Appraisal and Valuation Policy","id":11,"child_id":12},

{"Type":"Stem","url":"iim","description":"Commercial Real Estate Appraisal/Valuation Standard","id":12,"child_id":13},

{"Type":"Leaf","url":"har","description":"Commercial Real Estate Appraisal/Valuation Procedures","id":13}
        ]



// Given a parent ID, find and return the item in the data with that ID
const findParent = parentId => data.find(item => item.child_id === parentId)

// Create the tree by reducing the data to a root list
// that only contains "orphans". Items that do have a
// parent will be appended to those orphans' child lists
// instead
const tree = data.reduce((root, item) => {
  // Find the parent of the current item
  const parent = findParent(item.id)

  if (parent) {
    // If a parent was found, append the current item
    // to the parent's child list. Since objects are
    // passed by reference, it doesn't matter whether 
    // the parent is already in the root list  or not 
    // -- it always points to the same object
    parent.children = parent.children || []
    parent.children.push(item)
  } else {
    // Otherwise push the item to the root list
    root.push(item)
  }

  return root
}, [])

console.log(JSON.stringify(tree));

当前输出

[
  {
    "Type": "Root",
    "url": "abc",
    "description": "Enterprise Risk Management Framework",
    "id": 0,
    "child_id": 3,
    "children": [
      {
        "Type": "Stem",
        "url": "def",
        "description": "Risk Governance Framework",
        "id": 3,
        "child_id": 4,
        "children": [
          {
            "Type": "Stem",
            "url": "mno",
            "description": "Wholesale Credit Risk Framework",
            "id": 4,
            "child_id": 6,
            "children": [
              {
                "Type": "Stem",
                "url": "pqr",
                "description": "Wholesale Credit Risk Policy",
                "id": 6,
                "child_id": 7,
                "children": [
                  {
                    "Type": "Leaf",
                    "url": "vwx",
                    "description": "Wholesale Credit In-Business Quality Assurance Standard",
                    "id": 7
                  }
                ]
              },
              {
                "Type": "Stem",
                "url": "stu",
                "description": "Wholesale Credit Risk Policy",
                "id": 6,
                "child_id": 8,
                "children": [
                  {
                    "Type": "Leaf",
                    "url": "zab",
                    "description": "WCR Exception Management Standard",
                    "id": 8
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "Type": "Stem",
        "url": "ghi",
        "description": "Risk Governance Framework",
        "id": 3,
        "child_id": 9,
        "children": [
          {
            "Type": "Stem",
            "url": "nsr",
            "description": "Global Collateral Management Policy",
            "id": 9,
            "child_id": 10,
            "children": [
              {
                "Type": "Leaf",
                "url": "gov",
                "description": "WCR Collateral Management Standard",
                "id": 10
              }
            ]
          }
        ]
      },
      {
        "Type": "Stem",
        "url": "jkl",
        "description": "Risk Governance Framework",
        "id": 3,
        "child_id": 11,
        "children": [
          {
            "Type": "Stem",
            "url": "iit",
            "description": "Real Estate Appraisal and Valuation Policy",
            "id": 11,
            "child_id": 12,
            "children": [
              {
                "Type": "Stem",
                "url": "iim",
                "description": "Commercial Real Estate Appraisal/Valuation Standard",
                "id": 12,
                "child_id": 13,
                "children": [
                  {
                    "Type": "Leaf",
                    "url": "har",
                    "description": "Commercial Real Estate Appraisal/Valuation Procedures",
                    "id": 13
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  }
]

预期输出

{
  "id": 0,
  "type": "Root",
  "description": "Enterprise Risk Management Framework",
  "url": "abc",
  "children": [
    {
      "id": 3,
      "type": "Stem",
      "description": "Risk Governance Framework",
      "url": "def",
      "children": [
        {
          "id": 4,
          "type": "Stem",
          "description": "Wholesale Credit Risk Framework",
          "url": "ghi",
          "children": [
            {
              "id": 6,
              "type": "Stem",
              "description": "Wholesale Credit Risk Policy",
              "url": "jkl",
              "children": [
                {
                  "id": 7,
                  "type": "Leaf",
                  "description": "Wholesale Credit In-Business Quality Assurance Standard",
                  "url": "mno",
                  "children": [
                    
                  ]
                },
                {
                  "id": 8,
                  "type": "Leaf",
                  "description": "WCR Exception Management Standard",
                  "url": "pqr",
                  "children": [
                    
                  ]
                }
              ]
            }
          ]
        },
        {
          "id": 9,
          "type": "Stem",
          "description": "Global Collateral Management Policy",
          "url": "stu",
          "children": [
            {
              "id": 10,
              "type": "Leaf",
              "description": "WCR Collateral Management Standard",
              "url": "gov",
              "children": [
                
              ]
            }
          ]
        },
        {
          "id": 11,
          "type": "Stem",
          "description": "Real Estate Appraisal and Valuation Policy",
          "url": "iit",
          "children": [
            {
              "id": 12,
              "type": "Stem",
              "description": "Commercial Real Estate Appraisal/Valuation Standard",
              "url": "iim",
              "children": [
                {
                  "id": 13,
                  "type": "Leaf",
                  "description": "Commercial Real Estate Appraisal/Valuation Procedures",
                  "url": "har",
                  "children": [
                    
                  ]
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

您可以在 Map 中收集 id 和相应的目标对象。最初每个对象的 children 属性 都是空的。然后再次迭代数据以查找给定 id 的对象和给定 child_id 的对象并将后者对象放入前者的 children 数组中。 最后,获取假定 id 为 0 的根对象。

代码:

const data = [{"Type":"Root","url":"abc","description":"Enterprise Risk Management Framework","id":0,"child_id":3},{"Type":"Stem","url":"def","description":"Risk Governance Framework","id":3,"child_id":4},{"Type":"Stem","url":"def","description":"Risk Governance Framework","id":3,"child_id":9},{"Type":"Stem","url":"def","description":"Risk Governance Framework","id":3,"child_id":11},{"Type":"Stem","url":"ghi","description":"Wholesale Credit Risk framework","id":4,"child_id":6},{"Type":"Stem","url":"jkl","description":"Wholesale Credit Risk Policy","id":6,"child_id":7},{"Type":"Stem","url":"jkl","description":"Wholesale Credit Risk Policy","id":6,"child_id":8},{"Type":"Leaf","url":"mno","description":"Wholesale Credit In-Business Quality Assurance Standard","id":7},{"Type":"Leaf","url":"pqr","description":"WCR Exception Management Standard","id":8},{"Type":"Stem","url":"stu","description":"Global Collateral Management Policy","id":9,"child_id":10},{"Type":"Leaf","url":"gov","description":"WCR Collateral Management Standard","id":10},{"Type":"Stem","url":"iit","description":"Real Estate Appraisal and Valuation Policy","id":11,"child_id":12},{"Type":"Stem","url":"iim","description":"Commercial Real Estate Appraisal/Valuation Standard","id":12,"child_id":13},{"Type":"Leaf","url":"har","description":"Commercial Real Estate Appraisal/Valuation Procedures","id":13}];

const map = new Map(data.map(({child_id, ...rest}) => [rest.id, {...rest, children: []}]));

for (const {id, child_id} of data) {
    if (!child_id) continue;
    const child = map.get(child_id);
    child.parentId = id;
    map.get(id).children.push(child);
}

console.log(map.get(0));

这是一个基于 this answer 的示例。我已重构您的数据以使用 id/parentId。我已经删除了 duplicates/not 重复项(无论树有多少个子元素,数据集中的每个元素实际上只需要 1 个东西)。

var data=[
  {"Type":"Root","url":"abc","description":"Enterprise Risk Management Framework","id":0},
  {"Type":"Stem","url":"def","description":"Risk Governance Framework","id":3, "parentId": 0},
  {"Type":"Stem","url":"ghi","description":"Wholesale Credit Risk framework","id":4, "parentId": 3},
  {"Type":"Stem","url":"jkl","description":"Wholesale Credit Risk Policy","id":6, "parentId": 4},
  {"Type":"Leaf","url":"mno","description":"Wholesale Credit In-Business Quality Assurance Standard","id":7, "parentId": 6},
  {"Type":"Leaf","url":"pqr","description":"WCR Exception Management Standard","id":8, "parentId": 6},
  {"Type":"Stem","url":"stu","description":"Global Collateral Management Policy","id":9, "parentId": 3},
  {"Type":"Leaf","url":"gov","description":"WCR Collateral Management Standard","id":10, "parentId": 9},
  {"Type":"Stem","url":"iit","description":"Real Estate Appraisal and Valuation Policy","id":11, "parentId": 3},
  {"Type":"Stem","url":"iim","description":"Commercial Real Estate Appraisal/Valuation Standard","id":12,"parentId":11},
  {"Type":"Leaf","url":"har","description":"Commercial Real Estate Appraisal/Valuation Procedures","id":13, "parentId": 12}
];
        
        
const createDataTree = dataset => {
  const map = {};
  dataset.forEach(aData => map[aData.id] = aData);
  const dataTree = [];
  dataset.forEach(d => {
    if (d.parentId !== undefined) {
      map[d.parentId].children = map[d.parentId].children || [];
      map[d.parentId].children.push(map[d.id]);
    } else {
      dataTree.push(map[d.id]);
    }
  });
  return dataTree;
};

const tree = createDataTree(data);
console.log(tree);