基于子数组字段的JOLT数据分组转换需求
问题:按levelOne和levelTwo对JSON数据分层分组
需要将给定的JSON数据,按照子对象中的levelOne和levelTwo字段进行两级分组,转换成更适合UI展示的层级结构。
输入数据
{ "id": "101", "myLevel": "Beginner", "riskProducts": [ { "id": "1", "product": { "id": "2", "levelOne": "Equities", "levelTwo": "Global Developed Large Cap Equity", "productName": "Allianz Thematica Fund", "proposedAmountToInvest": "null", "proposedHoldings": "2", "unitPrice": "111.44" } }, { "id": "2", "product": { "id": "1", "levelOne": "Equities", "levelTwo": "Global Developed Large Cap Equity", "productName": "AB Low Volatility Equity Portfolio", "proposedAmountToInvest": "null", "proposedHoldings": "2", "unitPrice": "150.18" } }, { "id": "4", "product": { "id": "4", "levelOne": "Equities", "levelTwo": "US Large Cap Equity", "productName": "Franklin Technology Fund", "proposedAmountToInvest": "null", "proposedHoldings": "4", "unitPrice": "93.02" } }, { "id": "5", "product": { "id": "5", "levelOne": "Fixed Income", "levelTwo": "Global Aggregate Bonds", "productName": "PIMCO GIS Income Fund HKD Inc", "proposedAmountToInvest": "null", "proposedHoldings": "7", "unitPrice": "11.93" } } ] }
期望输出
{ "myLevel": "Beginner", "levelOne": [ { "id": "Equities", "levelTwo": [ { "id": "Global Developed Large Cap Equity", "product": [ { "id": "2", "productName": "Allianz Thematica Fund", "proposedHoldings": "2", "unitPrice": "111.44" }, { "id": "1", "productName": "AB Low Volatility Equity Portfolio", "proposedHoldings": "2", "unitPrice": "150.18" } ], "sPercentage": "0", "tPercentage": "0" }, { "id": "US Large Cap Equity", "product": [ { "id": "4", "productName": "Franklin Technology Fund", "proposedHoldings": "4", "unitPrice": "93.02" } ], "sPercentage": "0", "tPercentage": "0" } ] }, { "id": "Fixed Income", "levelTwo": [ { "id": "Global Aggregate Bonds", "product": [ { "id": "5", "productName": "PIMCO GIS Income Fund HKD Inc", "proposedAmountToInvest": "null", "proposedHoldings": "7", "unitPrice": "11.93" } ], "sPercentage": "0", "tPercentage": "0" } ] } ] }
解决方案(JavaScript实现)
const inputData = { "id": "101", "myLevel": "Beginner", "riskProducts": [ { "id": "1", "product": { "id": "2", "levelOne": "Equities", "levelTwo": "Global Developed Large Cap Equity", "productName": "Allianz Thematica Fund", "proposedAmountToInvest": "null", "proposedHoldings": "2", "unitPrice": "111.44" } }, { "id": "2", "product": { "id": "1", "levelOne": "Equities", "levelTwo": "Global Developed Large Cap Equity", "productName": "AB Low Volatility Equity Portfolio", "proposedAmountToInvest": "null", "proposedHoldings": "2", "unitPrice": "150.18" } }, { "id": "4", "product": { "id": "4", "levelOne": "Equities", "levelTwo": "US Large Cap Equity", "productName": "Franklin Technology Fund", "proposedAmountToInvest": "null", "proposedHoldings": "4", "unitPrice": "93.02" } }, { "id": "5", "product": { "id": "5", "levelOne": "Fixed Income", "levelTwo": "Global Aggregate Bonds", "productName": "PIMCO GIS Income Fund HKD Inc", "proposedAmountToInvest": "null", "proposedHoldings": "7", "unitPrice": "11.93" } } ] }; const transformData = (input) => { const result = { myLevel: input.myLevel, levelOne: [] }; // 用对象映射快速定位已存在的levelOne分组 const levelOneMap = {}; input.riskProducts.forEach(item => { const { levelOne, levelTwo, id, productName, proposedHoldings, unitPrice, proposedAmountToInvest } = item.product; // 处理一级分组:levelOne if (!levelOneMap[levelOne]) { const levelOneItem = { id: levelOne, levelTwo: [] }; levelOneMap[levelOne] = levelOneItem; result.levelOne.push(levelOneItem); } const currentLevelOne = levelOneMap[levelOne]; // 生成当前levelOne下的levelTwo映射,避免循环查找 const levelTwoMap = currentLevelOne.levelTwo.reduce((map, item) => { map[item.id] = item; return map; }, {}); // 处理二级分组:levelTwo if (!levelTwoMap[levelTwo]) { const levelTwoItem = { id: levelTwo, product: [], sPercentage: "0", tPercentage: "0" }; levelTwoMap[levelTwo] = levelTwoItem; currentLevelOne.levelTwo.push(levelTwoItem); } const currentLevelTwo = levelTwoMap[levelTwo]; // 提取需要的产品字段,保留可选的proposedAmountToInvest const productItem = { id, productName, proposedHoldings, unitPrice, ...(proposedAmountToInvest && { proposedAmountToInvest }) }; currentLevelTwo.product.push(productItem); }); return result; }; // 执行转换并打印结果 const outputData = transformData(inputData); console.log(JSON.stringify(outputData, null, 2));
核心原理说明
- 多级分组逻辑:通过两层分组实现,先按
levelOne聚合,再在每个levelOne分组下按levelTwo聚合 - 映射优化效率:使用对象存储已创建的分组项,避免每次查找都遍历数组,提升处理速度
- 字段提取:仅保留UI需要的产品字段,过滤冗余数据,同时默认添加
sPercentage和tPercentage字段
学习资源推荐
- 优先看MDN中文文档的数组方法(
forEach、reduce)和对象操作章节,掌握遍历与映射的基础逻辑 - 掘金平台搜索「JavaScript多级数组分组」,有大量实战案例讲解不同场景下的分组技巧
- 菜鸟教程的JavaScript对象与数组模块,适合巩固语法基础,理解数据结构操作
内容的提问来源于stack exchange,提问作者Mike Toleds
相关产品推荐
相关产品推荐

