如何创建含[index]子串时值转为数组的嵌套数据结构?
问题描述
输入数据
[{ "name": "outField2", "value": "something" }, { "name": "outField3[index].outField4", "value": "something" }, { "name": "outField3[index].outField5", "value": "something" }, { "name": "outField3[index].outField6.outField7", "value": "something" }]
期望输出
要求根据子串[index]生成结构:不含该子串的字段为对象,含该子串的字段为数组,最终输出如下:
{ "outField2": "something", "outField3[index]": [{ "outField4": "something", "outField5": "something", "outField6": { "outField7": "something" } }] }
当前代码问题
现有代码在不含[index]时能正常生成对象,但遇到含[index]的字段无法生成数组,尝试多种方案未解决:
function doThis(item, index) { let path = map[index].name.split("."); if (path.length > 1) { createNestedObject(mapOutput, path, map[index].value); } else { mapOutput[map[index].name] = map[index].value; }; }; function createNestedObject(element, path, value) { var lastElement = arguments.length === 3 ? path.pop() : false; for (var i = 0; i < path.length; i++) { if (path[i].includes('[index]')) { /*some logic here to push the child elements that do not contain [index] as an array into the ones that contain [index]*/ } else { element = element[path[i]] = element[path[i]] || {}; }; } if (lastElement) element = element[lastElement] = value; return element; }; const map = [{ "name": "outField2", "value": "something" }, { "name": "outField3[index].outField4", "value": "something" }, { "name": "outField3[index].outField5", "value": "something" }, { "name": "outField3[index].outField6.outField7", "value": "something" }]; let mapOutput = {}; map.forEach(doThis); let mapOutputJSON = JSON.stringify(mapOutput, null, 2); console.log(mapOutputJSON);
解决方案
修改createNestedObject函数,针对含[index]的字段做特殊处理:当遇到该字段时,初始化一个包含空对象的数组(如果不存在的话),后续子字段都挂载到数组的第一个元素上。
修改后的完整代码:
function doThis(item) { let path = item.name.split("."); if (path.length > 1) { createNestedObject(mapOutput, path, item.value); } else { mapOutput[item.name] = item.value; } }; function createNestedObject(element, path, value) { const lastElement = path.pop(); for (let i = 0; i < path.length; i++) { const key = path[i]; if (key.includes('[index]')) { // 初始化数组,若不存在则创建包含空对象的数组 element[key] = element[key] || [{}]; // 切换操作上下文到数组的第一个元素 element = element[key][0]; } else { // 普通对象字段,不存在则创建空对象 element[key] = element[key] || {}; element = element[key]; } } // 为最后一个字段赋值 element[lastElement] = value; return element; }; const map = [{ "name": "outField2", "value": "something" }, { "name": "outField3[index].outField4", "value": "something" }, { "name": "outField3[index].outField5", "value": "something" }, { "name": "outField3[index].outField6.outField7", "value": "something" }]; let mapOutput = {}; map.forEach(doThis); const mapOutputJSON = JSON.stringify(mapOutput, null, 2); console.log(mapOutputJSON);
关键逻辑说明
- 遍历路径时,遇到含
[index]的键:- 若该键不存在,创建包含空对象的数组,确保后续子字段有挂载目标
- 将操作上下文切换到数组的第一个元素,所有子字段都会被添加到这个元素中
- 普通键保持原有逻辑,不存在则创建空对象
- 最后将对应值赋值给路径的最后一个字段
运行这段代码后,即可得到预期的输出结构。
内容的提问来源于stack exchange,提问作者shanky
相关产品推荐
相关产品推荐

