如何实现递归函数按嵌套属性列表关联多份JSON5文件数据
实现思路
你的现有实现存在几个核心问题:
- 没有处理异步等待逻辑,
forEach搭配async不会等待所有请求完成,函数返回时关联操作可能还没执行完 - 强行按路径长度奇偶拆分逻辑没有必要,嵌套关联的核心逻辑是统一的:路径分段中,奇数位(从0开始数)是要关联的集合名,偶数位是关联用的匹配字段名
- 没有处理嵌套层级下的数组/单个值的通用替换逻辑,硬编码只处理第一层路径
完整可运行代码
async function getAllData(targetObj, nestedProperties) { // 深拷贝原对象避免修改原始数据,不需要可以删除该行 const result = JSON.parse(JSON.stringify(targetObj)); // 单条路径的递归处理函数 const processPath = async (currentObj, pathSegments, segmentIndex = 0) => { // 路径处理完成直接返回 if (segmentIndex >= pathSegments.length - 1) return; const collectionName = pathSegments[segmentIndex]; const matchKey = pathSegments[segmentIndex + 1]; // 要处理的字段不存在就跳过 if (currentObj[collectionName] === undefined) return; // 统一兼容数组和单个值两种字段格式 const items = Array.isArray(currentObj[collectionName]) ? currentObj[collectionName] : [currentObj[collectionName]]; // 批量并行查询同层级关联数据,提升性能 const resolvedItems = await Promise.all( items.map(async (item) => { // 如果当前项已经是关联后的对象,直接取匹配字段的值 const matchValue = typeof item === 'object' ? item[matchKey] : item; // 调用你的getData方法查询关联实体 const resolved = await getData(collectionName, { [matchKey]: matchValue }); // 递归处理下一级关联路径 await processPath(resolved, pathSegments, segmentIndex + 2); return resolved; }) ); // 替换原字段,保持和原始结构一致的数组/单个值格式 currentObj[collectionName] = Array.isArray(currentObj[collectionName]) ? resolvedItems : resolvedItems[0]; }; // 遍历所有关联路径依次处理 for (const path of nestedProperties) { const segments = path.split('.'); if (segments.length < 2) { console.error(`无效路径:${path}`); continue; } await processPath(result, segments); } return result; }
使用示例
// 先获取主对象 const mainObj = await getData('equations', {slug: 'mass-energy-equivalence'}); // 定义关联路径 const nestedProperties = [ 'categories.slug', 'constants.slug.units.slug', 'magnitudes.slug', 'units.slug', 'variables.slug.units.slug', 'values.units.slug' ]; // 执行关联合并 const mergedObj = await getAllData(mainObj, nestedProperties);
注意事项
- 如果你的
getData第二个参数直接接收slug值而非查询对象,把代码中调用getData的行替换为await getData(collectionName, matchValue)即可 - 支持任意层级的嵌套关联,不需要额外修改逻辑适配路径长度
内容的提问来源于stack exchange,提问作者Derian André
相关产品推荐
相关产品推荐

