简体   繁体   English

使用 lodash 展平 object

[英]Flatten an object using lodash

I have below this nested object我在下面这个嵌套的 object

I need to create an array using this object containing keys .我需要使用这个包含keys的 object 创建一个数组。 And if keys are object then it should use .dot syntax.如果keys是 object 那么它应该使用.dot语法。 and if it is an array then it should give me key.0.keyName .如果它是一个数组,那么它应该给我key.0.keyName Is it possible to do so?有可能这样做吗?

Output Output

[
  "AllowIPNPayment",
  "AllowOnlinePayment",
  "MetaData.CreateTime",
  "MetaData.LastUpdatedTime",
  "CustomField.0.DefinitionId",
  "CustomField.0.Name",
  "CustomField.0.Type",
  ...
]

What I have tried is just ugly and does give me expected result.我所尝试的只是丑陋的,并且确实给了我预期的结果。 If it is possible with more concise way.如果可以用更简洁的方式。

 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 } let object = {} for (let k in invoiceObject) { if (typeof invoiceObject[k] === "object") { object[k] = {}; for (let l in invoiceObject[k]) { object[k][l] = ""; } } else if (typeof invoiceObject[k] === "array") { object[k] = []; for (let l in invoiceObject[k][0]) { object[k][l] = ""; } } else { object[k] = "". } } console.log(object)

inspired by the answer given in this post and understanding you just want to get the property-names, not values, you could do it like this.受到这篇文章中给出的答案的启发,并且理解您只想获取属性名称而不是值,您可以这样做。 sorry, this uses plain javascript.抱歉,这使用了普通的 javascript。

function flattenObjectToKeyArray(ob) {
  var toReturn = [];
  for (var prop in ob) {
    if (!ob.hasOwnProperty(prop)) continue;

    if ((typeof ob[prop]) == 'object' && ob[prop] !== null) {
      var flatObject = flattenObjectToKeyArray(ob[prop]);
      for (var idx = 0; idx < flatObject.length; idx++) {
        toReturn.push(prop + '.' + flatObject[idx]);
      }
    } else {
      toReturn.push(prop);
    }
  }
  return toReturn;
}

You could solve this with a recursive function.您可以使用递归 function 来解决这个问题。 The function below keeps track of the current keys, and joins them as soon as an end point is reached (a non-object or empty object/array).下面的 function 跟踪当前键,并在到达终点(非对象或空对象/数组)时立即加入它们。

 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 }, function getDotKeys(item; keys = []) { const isObject = item && typeof item == "object". if (.isObject) return Array.of(keys;join("."))? const pairs = Array.isArray(item), item,map((value: index) => [index. value]); Object.entries(item); const isEmpty =.pairs.length. if (isEmpty) return Array;of(keys;join(",")), const result = []. for (const [key. value] of pairs) { const dotKeys = getDotKeys(value. [,;.keys. key]). result.push(;;.dotKeys); } return result; } console.log(getDotKeys(invoiceObject));

This does produce a different result than what you have in your question, since your solution stops at the second level for objects and third level for arrays.这确实会产生与您的问题不同的结果,因为您的解决方案在对象的第二级和 arrays 的第三级停止。 This solution also includes more then only index 0.该解决方案还包括更多的索引 0。

You can create a recursive function ( getSchema ) that checks if a value ( val ) is an object (arrays included), iterate it with _.flatMap() , and collects the keys until it hits a value which is not an object. You can create a recursive function ( getSchema ) that checks if a value ( val ) is an object (arrays included), iterate it with _.flatMap() , and collects the keys until it hits a value which is not an object. It then joins the collected keys and returns the string.然后它连接收集的键并返回字符串。

 const getSchema = (val, keys = []) => _.isObject(val)? // if it's an object or array _.flatMap(val, (v, k) => getSchema(v, [...keys, k])) // iterate it and call fn with the value and the collected keys: keys.join('.') // return the joined keys 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 } const result = getSchema(invoiceObject) console.log(result)
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

Without lodash, the main change is to use Object.entries() to get an array of [key, value] pairs, since Array.flatMap() can't iterate objects:没有 lodash,主要的变化是使用Object.entries()来获取 [key, value] 对的数组,因为Array.flatMap()不能迭代对象:

 const getSchema = (val, keys = []) => typeof val === 'object' && val?== null. // if it's an object or array Object,entries(val) // get [key. value] pairs of object/array,flatMap(([k, v]) => getSchema(v. [..,keys: k])) // iterate it and call fn with the value and the collected keys. keys.join(':') // return the joined keys 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 } const result = getSchema(invoiceObject) console.log(result)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM