RockerFlower RockerFlower - 5 months ago 126
Javascript Question

How to convert flat multi-branch data to hierarchical JSON?

[
{
"id": "a",
"pid": "a",
"name": "AA",
},
{
"id": "b",
"pid": "a",
"name": "BB",
},
{
"id": "c",
"pid": "a",
"name": "CC",
},
{
"id": "x",
"pid": "b",
"name": "XX",
}
]


Above is the data I got from the database. Every person has an
id
and a
pid
,
pid
points to the person's higher level person's
id
. If a person has highest level, the
id
equals
pid
.

I want to convert the raw data to hierarchical JSON, like this:

[
{
"id": "a",
"name": "AA",
"child": [
{
"id": "b",
"name": "BB"
"child": [
{
"id": "x",
"name": "XX"
}
]
},
{
"id": "c",
"name": "CC"
}
]
}
]


I'm using Node.js.

Answer

A proposal which creates a tree and takes an equal isand pid as a root for the tree. This solution works for unsorted data.

How it works:

Basically for every object in the array it takes as well the id for building a new object as the parentid for a new object.

So for example

{ "id": 6, "pid": 4 }

it generates first with id this property

"6": {
    "id": 6,
    "pid": 4
}

and then this property with pid

"4": {
    "children": [
        {
            "id": 6,
            "pid": 4
        }
    ]
},

and while all object treated like this, we finally get a tree.

If id === pid the root node is found. This is the object for the later return.

var data = [
        { "id": "f", "pid": "b", "name": "F" },
        { "id": "e", "pid": "c", "name": "E" },
        { "id": "d", "pid": "c", "name": "D" },
        { "id": "c", "pid": "b", "name": "C" },
        { "id": "a", "pid": "a", "name": "A" },
        { "id": "b", "pid": "a", "name": "B" }
    ],
    tree = function (data) {
        var r, o = Object.create(null);
        data.forEach(function (a) {
            a.children = o[a.id] && o[a.id].children;
            o[a.id] = a;
            if (a.id === a.pid) {
                r = a;
            } else {
                o[a.pid] = o[a.pid] || {};
                o[a.pid].children = o[a.pid].children || [];
                o[a.pid].children.push(a);
            }
        });
        return r;
    }(data);

console.log(tree);