antonyboom antonyboom - 20 days ago 6
Javascript Question

recursively transform json object

I need help with recursively transform json object into another json object.

My input object looks like this:

var my_obj = {
"id": 22,
"eventTypeId": 37,
"eventTypeName": "CommonOnly",
"parentEvent": {
"id": 21,
"eventTypeId": 35,
"eventTypeName": "FullTest",
"parentEvent": {
"id": 20,
"parentEvent": null,
"eventTypeId": 38,
"eventTypeName": "FullTest"
}
},
"childrenEvents": [
{
"id": 24,
"parentEventId": 22,
"eventTypeId": 36,
"eventTypeName": "BlindedTest",
"childrenEvents": []
},
{
"id": 23,
"parentEventId": 22,
"eventTypeId": 38,
"eventTypeName": "OneCustom",
"childrenEvents": []
}
]
}


The output I want is:

var my_obj = {
"id": 20,
"eventTypeId": 38,
"parentEvent": null,
"eventTypeName": "FullTest",
"childrenEvents": [{
"id": 21,
"eventTypeId": 35,
"eventTypeName": "FullTest",
"childrenEvents": [
{
"id": 22,
"eventTypeId": 37,
"eventTypeName": "CommonOnly",
"childrenEvents": [
{
"id": 24,
"parentEventId": 22,
"eventTypeId": 36,
"eventTypeName": "BlindedTest",
"childrenEvents": []
}, {
"id": 23,
"parentEventId": 22,
"eventTypeId": 38,
"eventTypeName": "OneCustom",
"childrenEvents": []
}
]
}
]
}]


}

So I want to be able to get an object where the second
parentEvent
with
parentEvent = null
has became a root element, with an array
childrenEvents
, inside children array will be first parent event object with its own
childrenEvents
array and inside of this array I want to put existing root object with its own
childrenEvents
array

I appreciate if somebody could help me to resolve it. Thanks in advance.

My attempt

function rebuild(input)
{
var childrenEvents = [] ;

for ( f in input.parentEvent ) // we may have attributes other than "age"
if (f.parentEvent == null) {
f.parentEvent.push(childrenEvents);
}
else {
f.parentEvent.push(input.parentEvent[f]);
}

if (input.childrenEvents.length !== 0)
{
input.parentEvent[f].push(input.childrenEvents)
}

return input;
}

console.log(rebuild( $scope.myObj))

});


plunker

Answer

You could use an object to build all dependencies and take only the one with

parentEvent === null

as tree.

var my_obj = { "id": 22, "eventTypeId": 37, "eventTypeName": "CommonOnly", "parentEvent": { "id": 21, "eventTypeId": 35, "eventTypeName": "FullTest", "parentEvent": { "id": 20, "parentEvent": null, "eventTypeId": 38, "eventTypeName": "FullTest" } }, "childrenEvents": [{ "id": 24, "parentEventId": 22, "eventTypeId": 36, "eventTypeName": "BlindedTest", "childrenEvents": [] }, { "id": 23, "parentEventId": 22, "eventTypeId": 38, "eventTypeName": "OneCustom", "childrenEvents": [] }] },
    tree = function (data, root) {
        function iter(a) {
            var parent;
            if (a.childrenEvents && Array.isArray(a.childrenEvents)) {
                a.childrenEvents.forEach(iter);
            }
            a.childrenEvents = o[a.id] && o[a.id].childrenEvents;
            o[a.id] = a;
            if (a.parentEvent === root) {
                r = a;
            } else {
                if (a.parentEvent && 'id' in a.parentEvent) {
                    parent = a.parentEvent.id;
                }
                if ('parentEventId' in a) {
                    parent = a.parentEventId;
                }
                if (parent !== undefined) {
                    o[parent] = o[parent] || {};
                    o[parent].childrenEvents = o[parent].childrenEvents || [];
                    o[parent].childrenEvents.push(a);
                }
            }
            if (a.parentEvent) {
                iter(a.parentEvent);
                delete a.parentEvent;
            }
        }

        var r, o = {};
        iter(data);
        return r;
    }(my_obj, null);

console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments