简体   繁体   中英

Flat JSON to nested JSON using JavaScript/NodeJS

I have a flat JSON response from server. I need to convert it to nested JSON. I can do that using for loop but I am looking for a more efficient way if there is one. The JSON I have is for monthly sales figures. I need to convert this flat response to masterAgent-subAgent data for each month. A master agent can have multiple sub agents and I need to show thee report for each month. Here is the sample JSON array:

[{"month": "Jan-2017", "agentId": "123", "areaCode": "12", "sale": "290 units", "masterAgent": null},
{"month": "Jan-2017", "agentId": "123.1", "areaCode": "121", "sale": "120 units", "masterAgent": "121"},
{"month": "Jan-2017", "agentId": "123.2", "areaCode": "122", "sale": "170 units", "masterAgent": "121"},
{"month": "Feb-2017", "agentId": "124", "areaCode": "13", "sale": "290 units", "masterAgent": null},
{"month": "Feb-2017", "agentId": "124.1", "areaCode": "131", "sale": "120 units", "masterAgent": 124},
{"month": "Feb-2017", "agentId": "124.1", "areaCode": "132", "sale": "170 units", "masterAgent": 124}]

The desired output is:

{
    "data": [{
            "month": "Jan-2017",
            "agentId": "123",
            "sale": "290 units",
            "areaCode": "12",
            "subAgentData": [{
                "agentId": "123.1",
                "sale": "120 units",
                "areaCode": "121"
            }, {
                "agentId": "123.2",
                "sale": "170 units",
                "areaCode": "122"
            }]
        },
        {
            "month": "Feb-2017",
            "agentId": "124",
            "sale": "290 units",
            "areaCode": "13",
            "subAgentData": [{
                "agentId": "124.1",
                "sale": "120 units",
                "areaCode": "131"
            }, {
                "agentId": "124.2",
                "sale": "170 units",
                "areaCode": "132"
            }]
        }
    ]
}

What is the best way to achieve this?

This could easily be done using lodash

 var items = [{"month": "Jan-2017", "agentId": "123", "areaCode": "12", "sale": "290 units", "masterAgent": null}, {"month": "Jan-2017", "agentId": "123.1", "areaCode": "121", "sale": "120 units", "masterAgent": "121"}, {"month": "Jan-2017", "agentId": "123.2", "areaCode": "122", "sale": "170 units", "masterAgent": "121"}, {"month": "Feb-2017", "agentId": "124", "areaCode": "13", "sale": "290 units", "masterAgent": null}, {"month": "Feb-2017", "agentId": "124.1", "areaCode": "131", "sale": "120 units", "masterAgent": 124}, {"month": "Feb-2017", "agentId": "124.1", "areaCode": "132", "sale": "170 units", "masterAgent": 124}]; // wrap item list into lodash chain var groupedItems = _.chain(items) // first group reports by month field // results will have the form { [month1]: [list1], [month2]: [list2] } .groupBy('month') // discard the month key and get an array of the list part only .values() // process the array one list of monthly reports as a time .map(function (monthlyReports) { // process each report in list return monthlyReports.reduce(function (tmp, report) { // check the masterAgent for masterAgent report if (report.masterAgent === null) { // map masterAgent report fields into template tmp.month = report.month; tmp.agentId = report.agentId; tmp.areaCode = report.areaCode; tmp.sale = report.sale; } else { // map subAgentReport fields tmp.subAgentData.push({ agentId: report.agentId, areaCode: report.areaCode, sale: report.sale, }) } return tmp; }, { // initialize the template agentId: null, areaCode: null, month: null, sale: null, subAgentData: [] }) }) // escape lodash chain and realize value .value(); console.log(groupedItems); 
 <script src="https://cdn.jsdelivr.net/lodash/4/lodash.min.js"></script> 

here is my working code for you at jsFiddle flat json array convert to recursive json tree

        function getNestedChildren(arr, parent) {
        var out = []
        for(var i in arr) {
            if(arr[i].masterAgent == parent) {
                var subAgentData = getNestedChildren(arr, arr[i].areaCode)

                if(subAgentData.length) {
                    arr[i].subAgentData = subAgentData
                }
                out.push(arr[i])
            }
        }
        return out
    }


    var flat_array = [{"month": "Jan-2017", "agentId": "123", "areaCode": "12", "sale": "290 units", "masterAgent": 0},
    {"month": "Jan-2017", "agentId": "123.1", "areaCode": "121", "sale": "120 units", "masterAgent": "121"},
    {"month": "Jan-2017", "agentId": "123.2", "areaCode": "122", "sale": "170 units", "masterAgent": "121"},
    {"month": "Feb-2017", "agentId": "124", "areaCode": "13", "sale": "290 units", "masterAgent": 0},
    {"month": "Feb-2017", "agentId": "124.1", "areaCode": "131", "sale": "120 units", "masterAgent": 124},
    {"month": "Feb-2017", "agentId": "124.1", "areaCode": "132", "sale": "170 units", "masterAgent": 124}]

    var nested = getNestedChildren(flat_array, 0)

    console.log(nested)

For general use, recursive function are:

function getNestedChildren(arr, parent) {
var out = []
for(var i in arr) {
    if(arr[i].parent == parent) {
        var children = getNestedChildren(arr, arr[i].id)

        if(children.length) {
            arr[i].children = children
        }
        out.push(arr[i])
    }
  }
  return out
 }

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