
本文详解如何使用 JavaScript 的 map() 方法递归映射原始项目数据,将扁平的 projects → workItems → subtasks 层级关系转换为结构清晰、ID 自动编号、日期正确解析的多层嵌套对象数组。
本文详解如何使用 javascript 的 `map()` 方法递归映射原始项目数据,将扁平的 `projects → workitems → subtasks` 层级关系转换为结构清晰、id 自动编号、日期正确解析的多层嵌套对象数组。
在项目管理、甘特图渲染或任务分解(WBS)等场景中,常需将线性嵌套的数据源(如 API 返回的 projects 数组,其每个元素含 workItems,而部分 workItem 又含 subtasks)转化为具备层级语义的嵌套结构。核心挑战在于:避免扁平化展开、保持父子关系、生成可读且唯一层级 ID(如 1.2.3),并确保日期、数值等字段类型准确。
以下是一个健壮、可扩展的实现方案:
✅ 正确做法:逐层 map + 动态 ID 生成
const newProjects = projects.map((project, projectIndex) => {
// 项目级 ID 从 1 开始(非 0)
const projectId = projectIndex + 1;
return {
TaskID: projectId,
ProjectNo: project.projectNumber?.toString() || '',
TaskName: project.projectTitle || '',
StartDate: project.projectStart ? new Date(project.projectStart) : null,
EndDate: project.projectEnd ? new Date(project.projectEnd) : null,
subtasks: (project.workItems || []).map((workItem, workIndex) => {
const workId = `${projectId}.${workIndex + 1}`;
return {
TaskID: workId,
TaskName: workItem.name || '',
StartDate: project.projectStart ? new Date(project.projectStart) : null,
Duration: workItem.duration || 30, // 建议优先取自数据,fallback 默认值
Progress: workItem.progress || 150,
comments: workItem.comments || '',
// 深度嵌套:支持 workItem 自带 subtasks(如示例中的 design/workshop/site)
subtasks: (workItem.subtasks || []).map((subtask, subIndex) => {
return {
TaskID: `${workId}.${subIndex + 1}`,
TaskName: subtask.name || '',
StartDate: project.projectStart ? new Date(project.projectStart) : null,
Duration: subtask.duration || 30,
Progress: subtask.progress || 150,
};
}),
};
}),
};
});
⚠️ 关键注意事项
-
空值防御:始终对
project.workItems、workItem.subtasks等可能为undefined或null的字段做(arr || []).map(...)安全处理,避免运行时错误; -
日期健壮性:
new Date("invalid")会返回Invalid Date,建议配合isValidDate()辅助函数校验(可选增强); -
ID 逻辑一致性:
.1,.1.1等格式依赖字符串拼接,若需数值计算(如排序),应额外保留level1,level2,level3数字字段; - 性能提示:该方案为纯函数式、无副作用,适用于中等规模数据(for...of 手动循环减少闭包开销;
-
扩展性设计:若未来需支持四级(如
subsubtasks),只需在最内层再嵌套一层map,结构完全对称。
? 总结
构建嵌套数组的本质是层级映射而非扁平展开。通过外层 map 创建父对象、内层 map 构建子数组,并利用索引组合生成语义化层级 ID,即可精准还原树状结构。务必加入空值检查与类型兜底,确保代码在真实数据波动下依然稳定可靠。此模式亦可轻松适配 React 渲染、ECharts 甘特图数据源或后端 JSON Schema 校验场景。










