简体   繁体   中英

Javascript Reduce or Flatten an object?

I have an object of data that I am working with that is dynamic and comes from a database call. If the record contains approval details, it will be contained in the object I get back, otherwise it will be omitted.

My problem is that I have an export method that is taking the object and turning it into an excel file, but this is only using the first level of the object, thus missing possible approval data.

I am trying to figure out how to flatten or reduce an object so that it brings all of the key/values to the parent level.

Example Code:

// Current Data
var obj = [{
    "toolSuite": "Enterprise Product",
    "toolStatus": "Active",
    "toolOwnerGroup": "PD",
    "toolTier": "1",
    "infoSec": "Yes",
    "sso": "?",
    "toolPortfolio": "Enterprise Product",
    "NeedByDate": "29-Jun-2018",
    "approvals": {
        "approval": { <--- Need to move all this data to the parent level
            "ApprovalID": "139",
            "TaskID": "232",
            "SubmissionDate": "2018-10-03T22:19:24.153",
            "WhoSubmitted": "Q1234",
            "Approver": "Q5678",
            "IsCanceled": "0",
            "ApproverFirst": "Bob",
            "ApproverLast": "Builder",
            "ApproverNTID": "bbuilder"
        }
    }
}, {
    "toolSuite": "Enterprise Product",
    "toolStatus": "Active",
    "toolOwnerGroup": "PD",
    "toolTier": "1",
    "infoSec": "Yes",
    "sso": "?",
    "toolPortfolio": "Enterprise Product",
    "NeedByDate": "29-Jun-2018",
    "ApprovalID": "139"
}]


// Desired Output
var obj = [{
    "toolSuite": "Enterprise Product",
    "toolStatus": "Active",
    "toolOwnerGroup": "PD",
    "toolTier": "1",
    "infoSec": "Yes",
    "sso": "?",
    "toolPortfolio": "Enterprise Product",
    "NeedByDate": "29-Jun-2018",
    "ApprovalID": "139",
    "TaskID": "232",
    "SubmissionDate": "2018-10-03T22:19:24.153",
    "WhoSubmitted": "Q1234",
    "Approver": "Q5678",
    "IsCanceled": "0",
    "ApproverFirst": "Bob",
    "ApproverLast": "Builder",
    "ApproverNTID": "bbuilder"

}, {
    "toolSuite": "Enterprise Product",
    "toolStatus": "Active",
    "toolOwnerGroup": "PD",
    "toolTier": "1",
    "infoSec": "Yes",
    "sso": "?",
    "toolPortfolio": "Enterprise Product",
    "NeedByDate": "29-Jun-2018",
}]

In the code above, the first object has the approvals.approval data. I am trying to bring this data to the parent level. It is not an array of data so there won't be duplicate keys.

I am currently using lodash in my project for other items but I wasn't able to find anything I could easily run this through to do what I need.

For this situation, is it something I need to reduce or flatten ? It should only ever be approvals.approval but if there is a way I can just specify a depth of say 3 and it can move this data to the parent, it would be ideal.

What approach should I be taking this with type of object?

No need for a library, just spread or Object.assign the approval object into the parent object, and then delete the approvals key:

 var obj=[{"toolSuite":"Enterprise Product","toolStatus":"Active","toolOwnerGroup":"PD","toolTier":"1","infoSec":"Yes","sso":"?","toolPortfolio":"Enterprise Product","NeedByDate":"29-Jun-2018","approvals":{"approval":{"ApprovalID":"139","TaskID":"232","SubmissionDate":"2018-10-03T22:19:24.153","WhoSubmitted":"Q1234","Approver":"Q5678","IsCanceled":"0","ApproverFirst":"Bob","ApproverLast":"Builder","ApproverNTID":"bbuilder"}}},{"toolSuite":"Enterprise Product","toolStatus":"Active","toolOwnerGroup":"PD","toolTier":"1","infoSec":"Yes","sso":"?","toolPortfolio":"Enterprise Product","NeedByDate":"29-Jun-2018","ApprovalID":"139"}]; Object.assign(obj[0], obj[0].approvals.approval); delete obj[0].approvals; console.log(obj[0]); 

If multiple items in the obj array have approvals: { approval: { ... } } properties that need to be transferred, then use a loop:

obj.forEach((object) => {
  const { approvals } = object;
  if (!approvals) return;
  Object.assign(object, approvals.approval);
  delete object.approvals;
});

I'd also recommend renaming your obj array to something else, if possible - it's an array, not a plain object, so perhaps call it something like arr to avoid confusion.

Using lodash this is somewhat more readable (via mergeWith and omit ) like this:

 var data = { "toolSuite": "Enterprise Product", "toolStatus": "Active", "toolOwnerGroup": "PD", "toolTier": "1", "infoSec": "Yes", "sso": "?", "toolPortfolio": "Enterprise Product", "NeedByDate": "29-Jun-2018", "approvals": { "approval": { "ApprovalID": "139", "TaskID": "232", "SubmissionDate": "2018-10-03T22:19:24.153", "WhoSubmitted": "Q1234", "Approver": "Q5678", "IsCanceled": "0", "ApproverFirst": "Bob", "ApproverLast": "Builder", "ApproverNTID": "bbuilder" } } } const result = _(data) .mergeWith(data.approvals.approval) .omit('approvals') .value() console.log(result) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script> 

In the case of having the data being an array you can simply map through since you do expect to get the same number of outputs as inputs:

 var data = [{ "toolSuite": "Enterprise Product", "toolStatus": "Active", "toolOwnerGroup": "PD", "toolTier": "1", "infoSec": "Yes", "sso": "?", "toolPortfolio": "Enterprise Product", "NeedByDate": "29-Jun-2018", "approvals": { "approval": { "ApprovalID": "139", "TaskID": "232", "SubmissionDate": "2018-10-03T22:19:24.153", "WhoSubmitted": "Q1234", "Approver": "Q5678", "IsCanceled": "0", "ApproverFirst": "Bob", "ApproverLast": "Builder", "ApproverNTID": "bbuilder" } } }, { "toolSuite": "Enterprise Product", "toolStatus": "Active", "toolOwnerGroup": "PD", "toolTier": "1", "infoSec": "Yes", "sso": "?", "toolPortfolio": "Enterprise Product", "NeedByDate": "29-Jun-2018" }] const result = _.map(data, obj => _(obj) .mergeWith(_.get(obj,'approvals.approval')) .omit('approvals') .value()) console.log(result) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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