Tips on transforming JSON into nested JSON using parent_id as a reference

In the given JSON array, each object contains properties 'is_parent' and 'parent_id'. If an object has children objects, its 'is_parent' property is set to 1, otherwise it is set to 0.

let list = [
    {id: 4, name: 'dd', is_parent: 1, parent_id: 0},
    /**/{id: 5, name: 'ee', is_parent: 0, parent_id: 4},
    /**/{id: 6, name: 'ff', is_parent: 1, parent_id: 5},
    /**//**/{id: 7, name: 'gg', is_parent: 0, parent_id: 6},

    {id: 8, name: 'hh', is_parent: 1, parent_id: 0},
    /**/{id: 9, name: 'ii', is_parent: 0, parent_id: 8},

    {id: 10, name: 'jj', is_parent: 1, parent_id: 0},
    /**/{id: 11, name: 'kk', is_parent: 1, parent_id: 10},
    /**//**/{id: 12, name: 'll', is_parent: 1, parent_id: 11},
    /**//**//**/{id: 13, name: 'mm', is_parent: 0, parent_id: 12},
],

The desired format of the above JSON array is as follows:

let array = [
    {
        id: 4,
        name: 'dd',
        is_parent: 1,
        parent_id: 0,
        children: [
            {id: 5, name: 'ee', is_parent: 0, parent_id: 4},
            {
                id: 6,
                name: 'ff',
                is_parent: 1,
                parent_id: 5,
                children: [
                    {id: 7, name: 'gg', is_parent: 0, parent_id: 6}
                ]
            }
        ]
    },

    {
        id: 8,
        name: 'hh',
        is_parent: 1,
        parent_id: 0,
        children: [
            {id: 9, name: 'ii', is_parent: 0, parent_id: 8}
        ]
    },

    {
        id: 10,
        name: 'jj',
        is_parent: 1,
        parent_id: 0,
        children: [
            {
                id: 11,
                name: 'kk',
                is_parent: 1,
                parent_id: 10,
                children: [
                    {
                        id: 12,
                        name: 'll',
                        is_parent: 1,
                        parent_id: 11,
                        children: [
                            {id: 13, name: 'mm', is_parent: 0, parent_id: 12}
                        ]
                    }
                ]
            }
        ]
    },
]

I attempted to achieve this using nested foreach loops, but encountered issues with the implementation.

Answer №1

Check out this solution.

function formatTreeData(data, root) {
                        const tree = {};
                        this.list.forEach(obj => ((tree[obj.parent_id] ??= {}).children ??= []).push(Object.assign(tree[obj.id] ??= {}, obj)));
                        return tree[root].children;
                    }

                    const data = {data: []};
                    const treeResult = Object.fromEntries(Object
                        .entries(data)
                        .map(([key, value]) => [key, getTree(value, '0')])
                    );

                console.log(treeResult);

This approach was inspired by this StackOverflow discussion on building tree arrays from flat arrays in JavaScript.

Answer №2

'use strict';
const generateTreeData = dataset => {
    const hashTable = Object.create(null);
    dataset.forEach(data => hashTable[data.id] = {...data, children: []});
    const treeData = [];
    dataset.forEach(data => {
        if(data.parent_id) {
            hashTable[data.parent_id].children.push(hashTable[data.id]);
        }
        else {
            treeData.push(hashTable[data.id]);
        }
    });
    console.log(JSON.stringify(treeData, null ,4))
    return treeData;
};

const dataList = [
        {id: 4, name: 'dd', is_parent: 1, parent_id: 0},
        /**/{id: 5, name: 'ee', is_parent: 0, parent_id: 4},
        /**/{id: 6, name: 'ff', is_parent: 1, parent_id: 5},
        /**//**/{id: 7, name: 'gg', is_parent: 0, parent_id: 6},

        {id: 8, name: 'hh', is_parent: 1, parent_id: 0},
        /**/{id: 9, name: 'ii', is_parent: 0, parent_id: 8},

        {id: 10, name: 'jj', is_parent: 1, parent_id: 0},
        /**/{id: 11, name: 'kk', is_parent: 1, parent_id: 10},
        /**//**/{id: 12, name: 'll', is_parent: 1, parent_id: 11},
        /**//**//**/{id: 13, name: 'mm', is_parent: 0, parent_id: 12},
    ];
generateTreeData(dataList);

I found this code snippet and made some enhancements based on this reference. It's a great example and works perfectly.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Safari and iOS users may not experience the onended() event triggering

Code snippet performs as expected on Chrome 80.0 and Firefox 74.0 (OSX 10.14.6). However, when testing on OSX Safari 13.0.5 or iOS (using Chrome, Safari), the <div> element fails to turn blue, suggesting that the onended callback is not triggering. C ...

Passing dynamic scope from Angular to a directive is a seamless process

I am working with a directive that retrieves an attribute value from an http call in the following manner: Controller app.controller("HomeController", function($scope){ $http.get("/api/source").then(function(res){ $scope.info = res.data }); }); ...

The AJAX success callback is malfunctioning

Below is the snippet I'm utilizing to interact with my web API controller titled Owner. However, despite everything appearing correct, the success function isn't triggering. Any suggestions on what might be causing this issue? $.ajax({ ...

Tips for dynamically modifying style mode in Vue.js

I am looking to implement a feature where the style can be changed upon clicking a button. In my scenario, I am using Sass/SCSS for styling. For example, I have three different styles: default.scss, dark.scss, and system.scss. The code for dark.scss look ...

Unable to locate the Chart object within the chartjs-plugin-labels.js file

Hello there, I am currently working on an Angular project where I want to incorporate a chart plugin. To achieve this, I executed the following commands: npm install angular2-chartjs npm install chartjs-plugin-labels Following that, I imported it into my ...

Using React Native to share API and passing a Base64 string in place of an image when sharing to WhatsApp

I am facing difficulties in sharing a base64 image on WhatsApp. On both iOS and Android, the actual base 64 code is shared instead of the image. When I try to use iMessage or Email on iOS, the base64 images are converted and displayed correctly. However, ...

The customized sweet alert button is failing to trigger its designated function

I integrated vue-swal to show a pop-up dialog with customized functionality. However, I faced an issue while modifying the swal. In my modified version, there are 3 buttons each with specific actions that should be triggered upon clicking. But for some rea ...

Merge the chosen values from the drop-down menu into one string

Any suggestions would be greatly appreciated! I am currently developing an application using ASP.NET web forms that consists of a dropdown list and two list boxes. I want these elements to be cloned whenever a specific button is clicked. However, my issue ...

Utilizing Angular 2's Routerlink with *ngIf and Parameters

Currently, I am facing an issue with a routerlink that includes a parameter: http://localhost:4200/item/1 I am trying to figure out how to implement an *ngIf statement with a parameter.... Here is what I have attempted so far: <div *ngIf="router.url ...

When a Vue.js component is not wrapped in a <div> element, it will hide everything

My experience with vuejs and parcel has been quite interesting. In my main component App.vue, I call a subcomponent Hello.vue using <Hello/> within App's template. However, I encountered a strange bug - if the <Hello/> is not wrapped insid ...

Hide the content within a table row by setting the display to

I need to hide the div with the id "NoveMeses" if all h3 elements display "N.A." Is there a way to achieve this? If both h3 elements in row1 and row2 contain the text "N.A.", I want the div NoveMeses to be hidden. Below is the code snippet using AngularJ ...

Perform an AJAX call from the main file after inserting data using AJAX beforehand

I am in need of assistance with a question I have. On a page, an AJAX function is executed after the page finishes loading, creating a table in PHP that contains two buttons: one for changing passwords and the other for deleting. This table is then injecte ...

Guide on creating a Discord bot that can delete its own message in a private message (DM) using Discord.js

Working on my Discord.js Discord bot, I'm exploring the option of having the bot delete its own message from a DM chat. Is it feasible to achieve this and if so, what code should I use? Attempting msg.delete() is throwing an error mentioning that this ...

The responses from Fetch and Postman vary in their outputs

While developing my react flask-rest site, I came across some unexpected behavior related to a specific issue. When I send a get request to the domain/api/users/1 endpoint in Postman where 1 represents the id of a deleted database element, I receive a resp ...

Utilize JavaScript to load an external script at the bottom of the body for improved website performance

On my website, I am utilizing the Mobile ESP script to determine whether visitors are accessing it from a mobile device or desktop. Depending on the type of device, I dynamically load the necessary scripts and CSS stylesheets for optimal navigation. Howev ...

The Bootstrap modals seem to be invisible within the Rails application

Currently, I am integrating jquery into the devise views of a sample rails application. My intention is to test it on a sample app before implementing it in a production code. The controller and view for welcome are already set up. The routes.rb file loo ...

Progress bar carousel component based on advancement movements

Here is the mockup I am working with: https://i.sstatic.net/bIepQ.png So far, I have made good progress with this code: https://codesandbox.io/s/codepen-with-react-forked-16t6rv?file=/src/components/TrendingNFTs.js However, I am facing a couple of challe ...

The placement of the React.js/Next.js Loader is incorrect on the page

While I was trying to display a Loader over everything during data fetching from my API, I encountered a situation where the Loader was not appearing at the expected top level but inside the page itself. Even though the HTML tree showed it at the top level ...

Adding a sign at the center of a map in React-Leaflet

One of the features I added to the map is a center indicator sign. <MapContainer fullscreenControl={true} center={center} zoom={18} maxNativeZoom = {22} maxZoom={22} classNa ...

PHP code to eliminate elements from an array that fall within a specific time range

I am attempting to retrieve elements from an array based on a specified criteria where the values fall within a time range but yield no results. Here is an example of the source array: Array ( [0] => Array ( [start] => 12:00:00 ...