Search code examples
javascriptnode.jsjavascript-objects

Reformatting deeply nested JSON object with varying length into an array of simplified objects


I'm using a map-reduce function to merge multiple data inputs into a single object as mentioned here.

The received reduced Object is in the following format:

{
    "2019-04-02T00:00:00-04:00": {
        "2019-04-02T09:00:00-04:00": {
            "2019-04-02T18:00:00-04:00": {
                "[MET] L2 - NB": {
                    "attendees": [
                        "Lex Luthor",
                        "Lois Lane"
                    ]
                },
                "[MET] L2 -  CS": {
                    "attendees": [
                        "General Zod",
                        "Clark Kent"
                    ]
                }
            }
        }
    },
    "2019-04-03T00:00:00-04:00": {
        "2019-04-03T09:00:00-04:00": {
            "2019-04-03T18:00:00-04:00": {
                "[MET] L2 - NB": {
                    "attendees": [
                        "Lex Luthor",
                        "Lois Lane"
                    ]
                },
                "[MET] L2 -  CS": {
                    "attendees": [
                        "General Zod",
                        "Clark Kent"
                    ]
                }
            }
        }
    }
}

However I'm looking for a way to reformat it into an array of objects which will allow to iterate through the objects and access all the data easily :

[
    {
        Date: "2019-04-02T00:00:00-04:00",
        StartTimeLocalized: "2019-04-02T09:00:00-04:00",
        EndTimeLocalized: "2019-04-02T18:00:00-04:00",
        LabelWithCompany: "[MET] L2 - NB",
        attendees: [
            "Lex Luthor",
            "Lois Lane"
        ]
    }, {
        Date: "2019-04-02T00:00:00-04:00",
        StartTimeLocalized: "2019-04-02T09:00:00-04:00",
        EndTimeLocalized: "2019-04-02T18:00:00-04:00",
        LabelWithCompany: "[MET] L2 -  CS",
        attendees: [
            "General Zod",
            "Clark Kent"
        ]
    },
    {
        Date: "2019-04-03T00:00:00-04:00",
        StartTimeLocalized: "2019-04-03T09:00:00-04:00",
        EndTimeLocalized: "2019-04-03T18:00:00-04:00",
        LabelWithCompany: "[MET] L2 -  CS",
        attendees: [
            "Lex Luthor",
            "Lois Lane"
        ]
    },
    {
        Date: "2019-04-03T00:00:00-04:00",
        StartTimeLocalized: "2019-04-03T09:00:00-04:00",
        EndTimeLocalized: "2019-04-03T18:00:00-04:00",
        LabelWithCompany: "[MET] L2 -  CS",
        attendees: [
            "General Zod",
            "Clark Kent"
        ]
    }
]

Solution

  • You could take a dynamic approach by handing over an array of nested keys and take all keys for new objects.

    function mapNestedObjects(object, keys) {
        function getNested(source, target, index) {
            Object.entries(source).forEach(([key, value]) => {
                if (index + 1 < keys.length) {
                    getNested(value, { ...target, [keys[index]]: key }, index + 1);
                } else {
                    result.push({ ...target, [keys[index]]: key, ...value });
                }
            });
        }
    
        var result = [];
        getNested(object, {}, 0);
        return result;
    }
    
    var object = { "2019-04-02T00:00:00-04:00": { "2019-04-02T09:00:00-04:00": { "2019-04-02T18:00:00-04:00": { "[MET] L2 - NB": { attendees: ["Lex Luthor", "Lois Lane"] }, "[MET] L2 -  CS": { attendees: ["General Zod", "Clark Kent"] } } } }, "2019-04-03T00:00:00-04:00": { "2019-04-03T09:00:00-04:00": { "2019-04-03T18:00:00-04:00": { "[MET] L2 - NB": { attendees: ["Lex Luthor", "Lois Lane"] }, "[MET] L2 -  CS": { attendees: ["General Zod", "Clark Kent"] } } } } },
        keys = ["Date", "StartTimeLocalized", "EndTimeLocalized", "LabelWithCompany"],
        result = mapNestedObjects(object, keys);
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }