Generating a JSON tree hierarchy from an array of nested objects

I have a JSON array of objects that looks like this:

[{
    "vehicleid": 3,
    "name": "Teste2VDD",
    "brand": "Scania",
    "model": "6x2",
    "class": "class1",
    "region": "Curitiba",
    "customer": "Cliente A",
    "customerid": 1
},
{
    "vehicleid": 1,
    "name": "Teste1",
    "brand": "Volkswagen",
    "model": "5x3",
    "class": "class1",
    "region": "Curitiba",
    "customer": "Cliente A",
    "customerid": 1
},
{
    "vehicleid": 2,
    "name": "Teste3VDD",
    "brand": "Volkswagen",
    "model": "6x2",
    "class": "class2",
    "region": "Curitiba",
    "customer": "Cliente A",
    "customerid": 1
},
{
    "vehicleid": 5,
    "name": "Teste4VDD",
    "brand": "Scania",
    "model": "6x4",
    "class": "class2",
    "region": "Curitiba",
    "customer": "Novo",
    "customerid": 2
},
{
    "vehicleid": 6,
    "name": "Teste5VDD",
    "brand": "Scania",
    "model": "5x5",
    "class": "class2",
    "region": "Curitiba",
    "customer": "Novo",
    "customerid": 2
},
{
    "vehicleid": 7,
    "name": "veiculo",
    "brand": "Scania",
    "model": "5x4",
    "class": "class1",
    "region": "Porto Alegre",
    "customer": "Cliente3",
    "customerid": 3
},
{
    "vehicleid": 8,
    "name": "veiculo65",
    "brand": "Volkswagen",
    "model": "5x4",
    "class": "class3",
    "region": "Porto Alegre",
    "customer": "Cliente3",
    "customerid": 3
},
{
    "vehicleid": 11,
    "name": "Veiculo de teste h",
    "brand": "Scania",
    "model": "5x3",
    "class": "class3",
    "region": "Belo Horizonte",
    "customer": "Cliente de teste h",
    "customerid": 10
},
{
    "vehicleid": 13,
    "name": "Nome 3",
    "brand": "Volkswagen",
    "model": "6x3",
    "class": "class3",
    "region": "Belo Horizonte",
    "customer": "Cliente de teste h",
    "customerid": 10
},
{
    "vehicleid": 12,
    "name": "Nome",
    "brand": "Volvo",
    "model": "6x3",
    "class": "class3",
    "region": "Belo Horizonte",
    "customer": "Cliente de teste h",
    "customerid": 10
}]

I am looking to create a tree hierarchy based on certain filter parameters.

The first level will always be the customer, and the last level will always be the vehicle.

For example:

1 - Filtering the tree by Customer would result in the tree being ordered by Customer, with each customer's children representing their associated Vehicles:

[{
    "attr": {
        "type": "customer"
    },
    "text": "Cliente A",
    "children": [
        {
            "id": 1,
            "text": "Teste1",
            "attr": {
                "type": "vehicle",
                "title": "Teste1"
            }
        },
        {
            "id": 2,
            "text": "Teste3VDD",
            "attr": {
                "type": "vehicle",
                "title": "Teste3VDD"
            }
        },
        {
            "id": 3,
            "text": "Teste2VDD",
            "attr": {
                "type": "vehicle",
                "title": "Teste2VDD"
            }
        }
    ]
},
{
    "attr": {
        "type": "customer"
    },
    "text": "Novo",
    "children": [
        {
            "id": 5,
            "text": "Teste4VDD",
            "attr": {
                "type": "vehicle",
                "title": "Teste4VDD"
            }
        },
        {
            "id": 6,
            "text": "Teste5VDD",
            "attr": {
                "type": "vehicle",
                "title": "Teste5VDD"
            }
        }
    ]
},
{
    "attr": {
        "type": "customer"
    },
    "text": "Cliente3",
    "children": [
        {
            "id": 7,
            "text": "veiculo",
            "attr": {
                "type": "vehicle",
                "title": "veiculo"
            }
        },
        {
            "id": 8,
            "text": "veiculo65",
            "attr": {
                "type": "vehicle",
                "title": "veiculo65"
            }
        }
    ]
},
{
    "attr": {
        "type": "customer"
    },
    "text": "Cliente",
    "children": [
        {
            "id": 11,
            "text": "Veiculo de teste h",
            "attr": {
                "type": "vehicle",
                "title": "Veiculo de teste h"
            }
        },
        {
            "id": 12,
            "text": "Nome",
            "attr": {
                "type": "vehicle",
                "title": "Nome"
            }
        },
        {
            "id": 13,
            "text": "Nome 3",
            "attr": {
                "type": "vehicle",
                "title": "Nome 3"
            }
        }
    ]
}]

2 - Filtering the tree by Brand would result in the tree being ordered by Customer, with each customer's children representing their associated Brands, followed by the Vehicles under each Brand.

3 - Filtering the tree by both Brand and Model would lead to the tree being ordered by Customer, with each customer's branches showing the respective Brands they own, then the Models under those Brands, and finally the Vehicles for each Model.

4 - If filtering by Brand, Model, and Region", the hierarchy would start at Customer, then show the Brands they are associated with, followed by Models, Regions, and finally Vehicles.

This pattern continues based on different combinations of filters chosen.

If anyone has an idea or solution for implementing this, I would greatly appreciate it!

Thank you in advance!

Answer №1

A unique approach involves utilizing a dynamic strategy by grouping based on specified keys or an object containing group names and keys, then constructing a nested structure using a hash table for each level.

function customGroupBy(arr, keys) {
    var result = [],
        temp = { _: result };

    data.forEach(function (a) {
        keys.reduce(function (r, k, i, kk) {
            var type = typeof k === 'object' ? Object.keys(k)[0] : k,
                key = typeof k === 'object' ? a[k[type]] : a[k];

            if (!r[key]) {
                r[key] = { _: [] };
                r._.push(i + 1 < kk.length
                    ? { attr: { type: type }, text: key, children: r[key]._ }
                    : { id: a.vehicleid, text: key, attr: { type: type, title: key } }
                );
            }
            return r[key];
        }, temp);
    });

    return result;
}

var data = [{ vehicleid: 3, name: "Teste2VDD", brand: "Scania", model: "6x2", class: "class1", region: "Curitiba", customer: "Cliente A", customerid: 1 }, { vehicleid: 1, name: "Teste1", brand: "Volkswagen", model: "5x3", class: "class1", region: "Curitiba", customer: "Cliente A", customerid: 1 }, { vehicleid: 2, name: "Teste3VDD", brand: "Volkswagen", model: "6x2", class: "class2", region: "Curitiba", customer: "Cliente A", customerid: 1 }, { vehicleid: 5, name: "Teste4VDD", brand: "Scania", model: "6x4", class: "class2", region: "Curitiba", customer: "Novo", customerid: 2 }, { vehicleid: 6, name: "Teste5VDD", brand: "Scania", model: "5x5", class: "class2", region: "Curitiba", customer: "Novo", customerid: 2 }, { vehicleid: 7, name: "veiculo", brand: "Scania", model: "5x4", class: "class1", region: "Porto Alegre", customer: "Cliente3", customerid: 3 }, { vehicleid: 8, name: "veiculo65", brand: "Volkswagen", model: "5x4", class: "class3", region: "Porto Alegre", customer: "Cliente3", customerid: 3 }, { vehicleid: 11, name: "Veiculo de teste h", brand: "Scania", model: "5x3", class: "class3", region: "Belo Horizonte", customer: "Cliente de teste h", customeri...
console.log(customGroupBy(data, ['customer', { vehicle: 'name' }]));
console.log(customGroupBy(data, ['brand', 'customer', { vehicle: 'name' }]));
.as-console-wrapper { max-height: 100% !important; top: 0; }

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

Transferring data from a JavaScript struct array to GLSL

Struggling to configure the values of a structure containing all the lights in my WebGL app using JavaScript. The layout of the structure is as follows: struct Light { vec4 position; vec4 ambient; vec4 diffuse; vec4 specular; vec3 spo ...

Add a fresh record only if it contains information and there are no existing duplicates present

Is it possible to create a note with both a title and text, under certain conditions? The title must not be empty The title cannot already exist in the system When attempting to check for duplicates within my array, the boolean value always returns true ...

jQuery's feature to select all elements except one and its children appears to be malfunctioning in Safari

My goal is fairly simple. I want to make the entire section clickable, except for the span and anything beneath it, so that the link redirects elsewhere. <section id="id" class="message"> <div class="message_body"> <font color="color"> ...

Teaching sessions along with the implementation of functions

I've created a set of input fields with the class replaceInput. The idea is to have a simple function that clears the value when the user focuses on the field, and then returns it to 'X' if the field is empty on focus out. My query is, coul ...

Acquiring the API through the callback function within a React application

I wrote a function that connects to an API and fetches data: import {API_KEY, API_URL} from "./constants"; export const getOperations = async (id, successCallback) => { try { const response = await fetch(`${API_URL}/tasks/${ ...

Trouble with Groovy HTTPBuilder while parsing correct JSON causing errors

As a newcomer to Groovy, I am facing an issue while trying to connect to the GitHub API from a Groovy script. The problem arises when HTTPBuilder attempts to parse the JSON response. Below is a simplified version of my script: @Grab(group='org.codeh ...

Why does starting up the Firebase emulators trigger the execution of one of my functions as well?

Upon running firebase emulators:start --only functions,firestore, the output I receive is as follows: $ firebase emulators:start --only functions,firestore i emulators: Starting emulators: functions, firestore ⚠ functions: The following emulators are ...

Having trouble utilizing NPM package within AWS Lambda environment, encountered issue with require() function

Recently, I developed a simple NPM package consisting of just two files. Here is the content of index.js: module.exports = { errors: { HttpError: require('./src/errors').HttpError, test: 'value' } } And here& ...

Sending a div class as a parameter to a JavaScript function

Wondering if it's possible to pass a div's class into a JavaScript function. I'm using SquareSpace so adding an id to the div is not an option, but it works fine with divs that have ids. JQuery is already loaded. This is my current train of ...

The message from Vee-validate indicates that the validator 'required_if' does not exist within the system

I'm currently implementing vee-validate version 3 with Vue 2.7 in my project. Specifically, this is the entry in my package.json file for vee-validate: "vee-validate": "^3.4.5", My issue lies with getting the required_if rule to f ...

Having trouble setting the image source in HTML with Node.js

I am a beginner with nodeJS and I am having trouble setting the src attribute of an img tag in my client side html. My node server is running on port 3000 and everything works fine when I visit http://localhost:3000. Here is the code from my server.js fil ...

A step-by-step guide on setting up a confirmation pop-up message using Gravity Forms

Has anyone attempted to implement a pop-up confirmation message in Gravity Forms? I am also looking to prevent the form from disappearing after submission. By the way, I have selected text as the confirmation type in my Gravity Form settings because I do ...

Discover the methods for accessing an array of IDs by implementing an event trigger in conjunction with checkboxes

Can you assist me with a dilemma I'm facing? I've developed a static form containing numerous checkboxes and checklists. My challenge arises when trying to integrate a JavaScript code that automatically selects subcategories when parent checkboxe ...

Connects URLs to the displayed outcomes in jQuery Auto-suggest Interface

This particular code snippet has been modified from a tutorial on jQuery autocomplete <!doctype html> <html lang="en> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> ...

Creating a RESTful API

To begin with, I am a newcomer to web frameworks and we are currently using Meteor. In our database, we have a collection of Students: Students = new Mongo.Collection('students'); At the moment, we have defined a Rest API as follows: // Maps t ...

A helpful software tool in Java that creates a comparison between two JSON files

Are there any Java libraries available for comparing the differences between two Json files? I am familiar with Zjsonpatch, DiffSon, and json-patch java libraries, but I'm curious if there are any other options out there that can perform the diff oper ...

What is the method to retrieve data in Vue when utilizing arrow functions?

When utilizing Vue and arrow functions in methods, we encounter the issue that arrow functions do not have a this keyword. The question then arises of how to access data properties such as list or object. export default { data() { return { list ...

What is the best way to calculate the width for each of the three elements in a row so that they all have 300px

Creating my own framework using flexbox has been an interesting journey. One of the major challenges I faced with flexbox is when dealing with an odd number of elements in a row, such as 3, 5, or 7. To tackle this issue, I decided to use JavaScript/jQuery. ...

How to retrieve the selected values of specific option tags using jQuery?

I have a situation where I need to select an option from a dropdown menu. Here is the code for the dropdown: <select id="customUser_id" name="customUser_id"> <option value="2" label="Friends Of Friends">Friends Of Friends</option> &l ...