创建递归 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);
我有平面文件格式的输入数据。我已经编写了 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);