Transform tree from DB format to JSON format in JavaScript

When working with database records, data is often stored in a flat structure with parent-child relationships defined by IDs. This tutorial shows how to transform such flat data into a hierarchical tree structure in JavaScript.

The Problem

Suppose we have an array of objects representing geographical regions from a database:

const arr = [
    {"id":7,"name":"Kuwait","parentId":2},
    {"id":4,"name":"Iraq","parentId":2},
    {"id":10,"name":"Qatar","parentId":2},
    {"id":2,"name":"Middle East","parentId":1},
    {"id":3,"name":"Bahrain","parentId":2},
    {"id":6,"name":"Jordan","parentId":2},
    {"id":8,"name":"Lebanon","parentId":2},
    {"id":1,"name":"Africa/Middle East","parentId":null},
    {"id":5,"name":"Israel","parentId":2},
    {"id":9,"name":"Oman","parentId":2}
];

console.log("Original flat structure:");
console.log(JSON.stringify(arr, null, 2));
Original flat structure:
[
  {
    "id": 7,
    "name": "Kuwait",
    "parentId": 2
  },
  {
    "id": 4,
    "name": "Iraq",
    "parentId": 2
  },
  {
    "id": 2,
    "name": "Middle East",
    "parentId": 1
  },
  {
    "id": 1,
    "name": "Africa/Middle East",
    "parentId": null
  }
]

Tree Transformation Function

We need to transform this flat structure into a hierarchical tree where each object contains a children array with its child nodes:

const transformTree = (data, root = null) => {
    const res = [];
    const map = {};
    
    data.forEach((el) => {
        // Initialize children array if it exists in map, or create empty array
        el.children = map[el.id] && map[el.id].children || [];
        map[el.id] = el;
        
        if (el.parentId === root) {
            // This is a root node
            res.push(el);
        } else {
            // This is a child node
            map[el.parentId] = map[el.parentId] || {};
            map[el.parentId].children = map[el.parentId].children || [];
            map[el.parentId].children.push(el);
        }
    });
    
    return res;
};

// Transform the flat array into tree structure
const treeData = transformTree(arr);
console.log("Transformed tree structure:");
console.log(JSON.stringify(treeData, null, 2));
Transformed tree structure:
[
  {
    "id": 1,
    "name": "Africa/Middle East",
    "parentId": null,
    "children": [
      {
        "id": 2,
        "name": "Middle East",
        "parentId": 1,
        "children": [
          {
            "id": 7,
            "name": "Kuwait",
            "parentId": 2,
            "children": []
          },
          {
            "id": 4,
            "name": "Iraq",
            "parentId": 2,
            "children": []
          },
          {
            "id": 10,
            "name": "Qatar",
            "parentId": 2,
            "children": []
          },
          {
            "id": 3,
            "name": "Bahrain",
            "parentId": 2,
            "children": []
          },
          {
            "id": 6,
            "name": "Jordan",
            "parentId": 2,
            "children": []
          },
          {
            "id": 8,
            "name": "Lebanon",
            "parentId": 2,
            "children": []
          },
          {
            "id": 5,
            "name": "Israel",
            "parentId": 2,
            "children": []
          },
          {
            "id": 9,
            "name": "Oman",
            "parentId": 2,
            "children": []
          }
        ]
      }
    ]
  }
]

How the Algorithm Works

The transformation algorithm uses a map-based approach:

  1. Create a map: Store each node by its ID for quick lookup
  2. Process each node: Initialize children array and add to map
  3. Build relationships: If parentId is null, it's a root node. Otherwise, add to parent's children
  4. Handle order independence: The map allows children to be processed before their parents

Alternative Implementation

Here's a more explicit version that's easier to understand:

const buildTree = (flatArray) => {
    const nodeMap = new Map();
    const roots = [];
    
    // First pass: create all nodes
    flatArray.forEach(item => {
        nodeMap.set(item.id, { ...item, children: [] });
    });
    
    // Second pass: build parent-child relationships
    flatArray.forEach(item => {
        const node = nodeMap.get(item.id);
        
        if (item.parentId === null) {
            roots.push(node);
        } else {
            const parent = nodeMap.get(item.parentId);
            if (parent) {
                parent.children.push(node);
            }
        }
    });
    
    return roots;
};

const alternativeTree = buildTree(arr);
console.log("Alternative implementation:");
console.log(JSON.stringify(alternativeTree, null, 2));
Alternative implementation:
[
  {
    "id": 1,
    "name": "Africa/Middle East",
    "parentId": null,
    "children": [
      {
        "id": 2,
        "name": "Middle East",
        "parentId": 1,
        "children": [
          {
            "id": 7,
            "name": "Kuwait",
            "parentId": 2,
            "children": []
          }
        ]
      }
    ]
  }
]

Conclusion

Converting flat database structures to hierarchical trees is essential for many applications. The map-based approach efficiently handles parent-child relationships regardless of data order, making it perfect for transforming database results into tree structures for UI components or data processing.

Updated on: 2026-03-15T23:19:00+05:30

518 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements