如何用Lodash扁平化嵌套对象,生成带点语法与数组索引的键数组?
简洁实现嵌套对象/数组的键路径生成
嘿,我来给你一个更简洁的递归实现方案,完美匹配你的需求!递归可以轻松处理任意深度的嵌套对象和数组,自动生成符合要求的点语法键路径。
核心思路
通过递归函数遍历每个层级:
- 遇到基础类型(字符串、布尔、数字等),直接将当前拼接好的路径存入结果数组。
- 遇到对象,继续递归遍历其键,拼接父路径与当前键。
- 遇到数组(假设数组元素结构一致),取第一个元素遍历,路径格式为
key.0.subKey(比如你的示例CustomField.0.DefinitionId)。
实现代码
function getKeyPaths(obj, parentPath = '') { let paths = []; for (const key of Object.keys(obj)) { // 拼接当前层级的路径 const currentPath = parentPath ? `${parentPath}.${key}` : key; const value = obj[key]; if (Array.isArray(value) && value.length > 0) { // 处理数组:取第一个元素递归,路径追加索引0 paths = paths.concat(getKeyPaths(value[0], `${currentPath}.0`)); } else if (typeof value === 'object' && value !== null) { // 处理非数组对象:继续递归深入 paths = paths.concat(getKeyPaths(value, currentPath)); } else { // 基础类型:将当前路径加入结果 paths.push(currentPath); } } return paths; } // 测试你的示例对象 const invoiceObject = { "AllowIPNPayment": false, "AllowOnlinePayment": false, "AllowOnlineCreditCardPayment": false, "AllowOnlineACHPayment": false, "domain": "QBO", "sparse": false, "Id": "16", "SyncToken": "1", "MetaData": { "CreateTime": "2020-03-25T15:10:40-07:00", "LastUpdatedTime": "2020-03-26T11:06:49-07:00" }, "CustomField": [{ "DefinitionId": "1", "Name": "Crew #", "Type": "StringType" }], "DocNumber": "1007", "TxnDate": "2020-03-03", "CurrencyRef": { "value": "USD", "name": "United States Dollar" }, "LinkedTxn": [{ "TxnId": "32", "TxnType": "Payment" }], "Line": [{ "Id": "1", "LineNum": 1, "Description": "Custom Design", "Amount": 750, "DetailType": "SalesItemLineDetail", "SalesItemLineDetail": { "ItemRef": { "value": "4", "name": "Design" }, "UnitPrice": 75, "Qty": 10, "TaxCodeRef": { "value": "NON" } } }, { "Amount": 750, "DetailType": "SubTotalLineDetail", "SubTotalLineDetail": {} } ], "TxnTaxDetail": { "TotalTax": 0 }, "CustomerRef": { "value": "13", "name": "uiool" }, "CustomerMemo": { "value": "Thank you for your business and have a great day!" }, "SalesTermRef": { "value": "3" }, "DueDate": "2020-04-02", "TotalAmt": 750, "ApplyTaxAfterDiscount": false, "PrintStatus": "NeedToPrint", "EmailStatus": "NotSet", "BillEmail": { "Address": "uiikoool" }, "Balance": 450 }; // 输出符合要求的键路径数组 console.log(getKeyPaths(invoiceObject));
代码说明
- 递归函数
getKeyPaths通过parentPath参数动态拼接路径,无需手动处理每一层嵌套。 - 数组处理逻辑:假设数组内元素结构一致,只遍历第一个元素生成路径(如果需要遍历所有数组元素,可以修改逻辑追加索引,但你的示例只需要
key.0.keyName格式,所以这个逻辑刚好匹配)。 - 自动处理任意深度的嵌套,比如会生成
Line.0.SalesItemLineDetail.ItemRef.value这种深层路径,解决了你原代码只能处理两层嵌套的问题。
对比原代码的优势
你的原代码只处理了两层嵌套,无法覆盖深层结构;而递归实现逻辑简洁、扩展性强,一次性解决所有层级的路径生成问题,完全符合你的预期输出格式。
内容的提问来源于stack exchange,提问作者Dark Knight
相关产品推荐
相关产品推荐

