redviper2100
redviper2100

Reputation: 265

Convert js object to hierarchic JSON structure

I have to create a JavaScript function to convert an object like the one bellow into a hierarchic JSON object.

The source is an HR employee list with it's corresponding manager.

Source Object:

Employee    Manager Title
Alfredo             general manager
Bergman     Alfredo senior engineer
Billy       Alfredo senior engineer
Johnson     Alfredo department manager
Angela      Johnson senior engineer
Anderson    Johnson senior engineer
Amy         Johnson department manager
Patsy       Amy     engineer
Jane        Amy     engineer

This is how the JSON object should look like:

var datasource = {
  'name': 'Alfredo',
  'title': 'general manager',
  'children': [
    { 'name': 'Bergman', 'title': 'senior engineer' },
    { 'name': 'Johnson', 'title': 'department manager',
      'children': [
        { 'name': 'Anderson', 'title': 'senior engineer' },
        { 'name': 'Amy', 'title': 'department manager',
          'children': [
            { 'name': 'Patsy', 'title': 'engineer'},
            { 'name': 'Jane', 'title': 'engineer'}
          ]
        },
        { 'name': 'Angela', 'title': 'senior engineer' }
      ]
    },
    { 'name': 'Billy', 'title': 'senior engineer' }
  ]
};

I have tried various methods unsuccessfully, but I am quite noob on JavaScript.

Any help or ideas will be appreciated.

Upvotes: 0

Views: 357

Answers (2)

tigerswithguitars
tigerswithguitars

Reputation: 2547

I think this should do what you want it to do: Iterate the list, building a map of all the employees, then sort the employees into the right set of children by the managers name, returning only the employee(s) that have no manager.

var entries = [{ name: 'Bergman', manager: 'Alfredo', title: 'senior engineer' }, { name: 'Billy', manager: 'Alfredo', title: 'senior engineer' }, { name: 'Johnson', manager: 'Alfredo', title: 'department manager' }, { name: 'Angela', manager: 'Johnson', title: 'senior engineer' }, { name: 'Anderson', manager: 'Johnson', title: 'senior engineer' }, { name: 'Amy', manager: 'Johnson', title: 'department manager' }, { name: 'Patsy', manager: 'Amy', title: 'engineer' }, { name: 'Jane', manager: 'Amy', title: 'engineer' }, { name: 'Alfredo', manager: '', title: 'general manager' }]
function build_org_chart(list) {
    var map = {}, node, managers = [], i;

    // Build the map of employees we will use later.
    for (i = 0; i < list.length; i += 1) {
        map[list[i].name] = i;
        list[i].directReports = []; // init the children
    }

    for (i = 0; i < list.length; i += 1) {
        node = list[i];
        if (node.manager != "") {

            // If the employee has a manager, find them
            var indexOfManager = map[node.manager];

            // Then add that employee to the managers children.
            list[indexOfManager].directReports.push(node);
        } else {

            // If they haven't got a manager, must be a boss.
            managers.push(node);
        }
    }

    // Return only the top bosses.
    return managers;
}

console.log(build_org_chart(entries));

Upvotes: 2

Nina Scholz
Nina Scholz

Reputation: 386550

You could take a single loop approach by using the relation of employee to manager and vice versa.

var data = [{ name: 'Bergman', manager: 'Alfredo', title: 'senior engineer' }, { name: 'Billy', manager: 'Alfredo', title: 'senior engineer' }, { name: 'Johnson', manager: 'Alfredo', title: 'department manager' }, { name: 'Angela', manager: 'Johnson', title: 'senior engineer' }, { name: 'Anderson', manager: 'Johnson', title: 'senior engineer' }, { name: 'Amy', manager: 'Johnson', title: 'department manager' }, { name: 'Patsy', manager: 'Amy', title: 'engineer' }, { name: 'Jane', manager: 'Amy', title: 'engineer' }, { name: 'Alfredo', manager: '', title: 'general manager' }],
    tree = function (data, root) {
        var o = {};
        data.forEach(function ({ name, manager, title }) {
            Object.assign(o[name] = o[name] || {}, { name, title }, o[name].children && { children: o[name].children });
            o[manager] = o[manager] || { name: null, title: null };
            o[manager].children = o[manager].children || [];
            o[manager].children.push(o[name]);
        });
        return o[root].children;
    }(data, '');

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

Upvotes: 1

Related Questions