如何展开含数组的对象数组?递归实现遇阻求助
解决方案
要实现你需要的嵌套JSON展开逻辑,核心是先提取所有扁平化字段,再根据最长数组的长度生成对应数量的对象,后续对象仅填充当前索引的有效值,重复字段设为undefined,同时添加排序用的key字段。
关键思路
- 扁平化字段提取:递归遍历原始JSON,把嵌套结构转换成
父键.子键格式的扁平字段,同时记录每个数组字段的元素列表 - 确定对象数量:以所有数组中长度最大的那个为基准,决定要生成多少个对象
- 填充对象内容:第一个对象填充所有字段的第一个有效值;后续对象仅填充当前索引存在值的字段,其余重复字段设为
undefined,并设置递增的key
修正后的代码
// 辅助函数:判断是否为对象 function isObject(item) { return item && typeof item === 'object' && !Array.isArray(item); } // 递归提取扁平化字段和对应的数据列表 function extractFlatFields(obj, parentKey = '', result = { fields: [], dataMap: {} }) { Object.entries(obj).forEach(([key, value]) => { const currentKey = parentKey ? `${parentKey}.${key}` : key; if (Array.isArray(value)) { // 处理数组:记录每个元素的扁平化数据 result.dataMap[currentKey] = value.map(item => { const itemData = {}; extractFlatFields(item, currentKey, { fields: [], dataMap: itemData }); // 把嵌套的扁平字段展开到当前层级 return Object.fromEntries( Object.entries(itemData).map(([k, v]) => [k.replace(`${currentKey}.`, ''), v]) ); }); // 把数组元素的子字段加入总字段列表 value.forEach(item => extractFlatFields(item, currentKey, result)); } else if (isObject(value)) { extractFlatFields(value, currentKey, result); } else { if (!result.fields.includes(currentKey)) { result.fields.push(currentKey); } // 非数组非对象的字段,用数组包装(方便统一处理) result.dataMap[currentKey] = [value]; } }); return result; } // 生成最终的展开结果 function expandNestedJSON(data) { const input = Array.isArray(data) ? data[0] : data; const { fields, dataMap } = extractFlatFields(input); // 找到最长的数组长度,确定要生成的对象数量 const maxLength = Math.max(...Object.values(dataMap).map(arr => arr.length)); // 生成每个对象 return Array.from({ length: maxLength }, (_, index) => { const obj = {}; fields.forEach(field => { // 拆分字段,找到对应的数组和子字段 const [rootKey, ...subKeys] = field.split('.'); const arr = dataMap[rootKey]; if (arr && arr[index]) { let value = arr[index]; // 处理子字段(比如b.c对应arr[index].c) for (const subKey of subKeys) { value = value?.[subKey]; } obj[field] = value !== undefined ? value : undefined; } else { // 只有第一个对象填充,后续设为undefined obj[field] = index === 0 ? dataMap[field]?.[0] : undefined; } }); // 设置key字段 obj.key = index + 1; return obj; }); } // 测试输入 const input = [ { a: '1', b: [ { c: '3', d: '4' }, { c: '5' }, { c: '7', d: '8' } ], f: [ { d: '6' }, { d: '9' } ], e: [ { g: '9' } ] } ]; // 生成结果 const output = expandNestedJSON(input); console.log(JSON.stringify(output, null, 2));
代码说明
extractFlatFields函数:递归遍历原始JSON,把所有嵌套字段转换成扁平格式(如b.c),同时用dataMap记录每个字段对应的数据列表(数组类型的字段直接存元素列表,非数组字段存单元素数组)expandNestedJSON函数:- 先获取最长数组的长度,确定要生成的对象总数
- 逐个生成对象:第一个对象填充所有字段的初始值;后续对象仅填充当前索引有对应值的字段,其余重复字段设为
undefined - 给每个对象添加递增的
key字段,用于排序
输出结果
运行代码后会得到你期望的输出:
[ { "a": "1", "b.c": "3", "b.d": "4", "f.d": "6", "e.g": "9", "key": 1 }, { "a": undefined, "b.c": "5", "b.d": undefined, "f.d": "9", "e.g": undefined, "key": 2 }, { "a": undefined, "b.c": "7", "b.d": "8", "f.d": undefined, "e.g": undefined, "key": 3 } ]
内容的提问来源于stack exchange,提问作者Dea N
相关产品推荐
相关产品推荐

