Constructing a hierarchical tree from a JSON structure

Here is an example of input JSON in the specified format.

var inputData = [{
    "TestScenario": "test1",
    "Application": "application1",
    "Market": "M1"
}, {
    "TestScenario": "test1",
    "Application": "application1",
    "Market": "M2"
}, {
    "TestScenario": "test1",
    "Application": "application1",
    "Market": "M3"
}, {
    "TestScenario": "test1",
    "Application": "application1",
    "Market": "M4"
}, {
    "TestScenario": "test2",
    "Application": "application2",
    "Market": "M5"
}, {
    "TestScenario": "test2",
    "Application": "application3",
    "Market": "M5"
}];

The desired tree structure should be as follows.

var outputData = [{
    "test1": {
        "application1": ["M1", "M2", "M3", "M4"]
    }
}, {
    "test2": {
        "application2": "M5",
        "application3": "M5"
    }
}];

Approach attempted:

I was successful in generating the tree structure for a single type of TestScenario but faced challenges when dealing with multiple types.

Successful code implementation for one TestScenario:

var dataEntries= [{
"TestScenario": "test1",
"Application": "application1",
"Market": "M1"
}, {
"TestScenario": "test1",
"Application": "application1",
"Market": "M2"
}, {
"TestScenario": "test1",
"Application": "application1",
"Market": "M3"
}, {
"TestScenario": "test1",
"Application": "application1",
"Market": "M4"
}];

var testCases = [];

for (const entry of dataEntries) {
    if(testCases.indexOf(entry.TestScenario) === -1) {
        testCases.push(entry.TestScenario);
  }
}

var marketArray = [];
var finalOutput = [];
var obj = {};
for (const b of dataEntries) {
    for (const c of testCases) {
        if (b.TestScenario === c) {
      obj[c] = {};
      obj[c][b.Application] = [];
      }
      if (finalOutput.indexOf(obj) === -1) {
        finalOutput.push(obj);
      }
    }
    
    for (const c of finalOutput) {
      var arr1 = Object.keys(c);
      for (const d of arr1) {
        if (b.TestScenario === d) {
            var arr2 = Object.keys(c[d]);
          for (const e of arr2) {
            if(b.Application === e) {
                            marketArray.push(b.Market);
                c[d][e] = marketArray;
            }
          }
        }
      }
    }
  }
  
console.log('Final Output', finalOutput);

Challenges encountered with multiple TestScenarios:

var dataEntries= [{
"TestScenario": "test1",
"Application": "application1",
"Market": "M1"
}, {
"TestScenario": "test1",
"Application": "application1",
"Market": "M2"
}, {
"TestScenario": "test1",
"Application": "application1",
"Market": "M3"
}, {
"TestScenario": "test1",
"Application": "application1",
"Market": "M4"
}, {
"TestScenario": "test2",
"Application": "application2",
"Market": "M5"
}, {
"TestScenario": "test2",
"Application": "application3",
"Market": "M5"
}];
var testCases = [];

for (const entry of dataEntries) {
    if(testCases.indexOf(entry.TestScenario) === -1) {
        testCases.push(entry.TestScenario);
  }
}

var marketArray = [];
var finalOutput = [];
var obj = {};
for (const b of dataEntries) {
    for (const c of testCases) {
        if (b.TestScenario === c) {
      obj[c] = {};
      obj[c][b.Application] = [];
      }
      if (finalOutput.indexOf(obj) === -1) {
        finalOutput.push(obj);
      }
    }
    
    for (const c of finalOutput) {
      var arr1 = Object.keys(c);
      for (const d of arr1) {
        if (b.TestScenario === d) {
            var arr2 = Object.keys(c[d]);
          for (const e of arr2) {
            if(b.Application === e) {
                            marketArray.push(b.Market);
                c[d][e] = marketArray;
            }
          }
        }
      }
    }
  }
  
console.log('Final Output', finalOutput);

Answer №1

One efficient approach involves leveraging the Array.reduce() method to group the data initially. Then, applying the Array.map() function on the result of Object.entries() can help achieve the desired structure.

For instance:

var inputJSON = [
  {"TestScenario": "test1", "Application": "application1", "Market": "M1"},
  {"TestScenario": "test1", "Application": "application1", "Market": "M2"},
  {"TestScenario": "test1", "Application": "application1", "Market": "M3"},
  {"TestScenario": "test1", "Application": "application1", "Market": "M4"},
  {"TestScenario": "test2", "Application": "application2", "Market": "M5"},
  {"TestScenario": "test2", "Application": "application3", "Market": "M5"}
];

let res = inputJSON.reduce((acc, {TestScenario, Application, Market}) =>
{
    acc[TestScenario] = acc[TestScenario] || {};
    acc[TestScenario][Application] = acc[TestScenario][Application] || [];
    acc[TestScenario][Application].push(Market);
    return acc;
}, {})

res = Object.entries(res).map(([key, val]) => ({[key]: val}));

console.log(res);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

Answer №2

A series of test scenarios were generated in an object, where the input data was used to populate these scenarios. The resulting output was then transformed into an array as per the specific formatting request.

var inputData = [ {
    "TestScenario": "test1",
    "Application": "application1",
    "Market": "M1"
}, {
    "TestScenario": "test1",
    "Application": "application1",
    "Market": "M2"
}, {
    "TestScenario": "test1",
    "Application": "application1",
    "Market": "M3"
}, {
    "TestScenario": "test1",
    "Application": "application1",
    "Market": "M4"
}, {
    "TestScenario": "test2",
    "Application": "application2",
    "Market": "M5"
},{
    "TestScenario": "test2",
    "Application": "application3",
    "Market": "M5"
}];

function transformData(input) {
    let output = {};
    
    input.forEach(function(object) {
       if (!output[object.TestScenario]) {
         output[object.TestScenario] = {};
       }
       
       if (!output[object.TestScenario][object.Application.trim()]) {
         output[object.TestScenario][object.Application.trim()] = [];
       }
       
       output[object.TestScenario][object.Application.trim()].push(object.Market.trim());
   });
   
  let outputArray = Object.keys(output).map(function(key) {
    let temp = {};
    temp[key] = output[key];
    
    return temp;
  });
  
  return outputArray;
}

console.log(transformData(inputData));

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

Issue with AngularJS: Dynamically generated tab does not become active or selected

Exploring an AngularJS code snippet that generates tabs upon clicking the new button. However, there's an issue where the newly created tab doesn't become active or selected automatically after creation. It seems like the one before the last tab ...

jQuery - Creating an organized hierarchy list

My website's DOM structure is shown below: <ul> <li id="Browse"> Browse <ul id="browse-one"> </ul> </li> </ul> At the bottom of the page, my jQuery script looks like this: $("#Brow ...

Easily transfer a Jquery array to a Rails controller action!

I'm struggling to understand how to send a query in JSON format to a Rails controller#action. Here's what I have: var myarray = []; ( with values ) This is the controller action I want to post to: def process end I've searched everywher ...

How to Update Previous Migration Files Including `JSONField` from `django_mysql.models` in Django?

Previously in Django, JSON fields could be used in models by utilizing django_mysql.models.JSONField. However, in the latest versions of Django, JSONField is no longer located in django_mysql.models. I have already made the necessary changes to my models.p ...

Switch up the URL and redirect by employing jQuery

Looking for a solution in jQuery to redirect based on user input? <form id="abc"> <input type="text" id="txt" /> </form> If you want to redirect to a URL constructed from the value of the text box, you can try this: var temp = $("#tx ...

As the user types input in real time, automatically adjust the form's value before submission

I'm looking for assistance in dynamically updating the value of a form submit button as the user types into an input field. <form> <input type="text" name="number" id="number" value = 0 /> <input type="submit" id="submit"> ...

Error: Unable to locate App.js file upon transition to Typescript

I'm in a bit of a bind with my Laravel project and I'm struggling to find a solution. I recently tried to upgrade from vue2 to vue3 with typescript, following this tutorial for the vue upgrade and this tutorial for typescript integration. However ...

Problem with laravel ajax request

I've spent the entire weekend trying to figure this out, but I can't seem to make it work. It works fine with the 'get' method, but not with 'post'. I'm using Laravel 4 and jQuery. Here's how my JavaScript looks: $ ...

Divs are the preferred placeholders over inputs and textareas

For the past few weeks, I have been trying to tackle a problem with creating placeholders that guide users on where to type. My goal is to make these placeholders disappear when users start typing and reappear if the div is empty again. All my attempts so ...

"Triggering CSS changes with the click of a

I am developing a basic calendar application in PHP and I would like to dynamically change the style of the <td> block based on user interactions. Specifically, I want to implement a behavior where once the "menuclick" class is active, the other cl ...

Utilizing Jcrop on an image loaded via ajax

Recently, I've been working on a project that involves uploading profile pictures to a server and storing them in a database using Ajax. While the basic functionality is working fine, I wanted to enhance the user experience by allowing users to crop t ...

Unable to utilize static files in node.js and express

Attempting to utilize node.js and express for crafting a chat client has proven to be a bit challenging. Whenever I attempt to incorporate external CSS or JS files, I encounter GET errors. My current configuration in index.js is as follows: var express = ...

Ensure that only a single onmouseover event is triggered when hovering over multiple elements

I want to create a simple code snippet like the one below: <span onmouseover="alert('hi')">Hello, <span onmouseover="alert('hello')">this</span> is a test</span> However, I need to ensure that when hovering ove ...

Picture cannot reemerge with SetTimeout

Browsing Experience: Users will simply tap on an image (group of spots) to make it disappear from the screen. Upon clicking the image, it will smoothly fade out. However, if the user does not interact with the image, a new one won't show up after 10 ...

How can I implement a page switch in vuejs by clicking on a name in a table list?

I'm currently working on a list page in VueJS and facing some challenges. Here is the code snippet: <template> <vue-good-table :columns="columns" :rows="row" :search-options="{ ...

Conceal table cells using jquery depending on the input value

Is there a way to hide the td elements when the input value is set to 0? I've been struggling to make it work. http://jsfiddle.net/zxpsd8x6/1/ <td><input type="radio" name="hideifvalue0" value"0"></td> <td><input type="rad ...

The loading time for the NextJS production build is unacceptably sluggish

Recently, I started working with NextJS and deployed my project on Netlify as a production build. However, I've noticed that there is a significant delay of around 3-4 seconds when navigating to a specific page using the next router. Surprisingly, thi ...

Instructions on utilizing the transpiled "main.js" file using gulp

As a novice in Angularjs 1.0, I encountered issues with my script and decided to use gulp to compile ec6 to ec5 by implementing the code provided below. The compilation process generated the file main.js. However, I am unsure about how to connect it when l ...

JavaScript vs. GSP: Exploring How to Trigger a Grails Action

There is an action in a controller that I need to modify. def deleteFiling={ obj.removeFiling() redirect(action:"list") } This action is triggered from a GSP: <g:link action="deleteFiling" id="${filingInstance.id}"> <img src="${resource(di ...

Building module dependencies in the Dojo dojo

I'm in the process of utilizing the Dojo builder to compile a unified file that encompasses all the necessary modules for my application, excluding the application itself. Below is an illustration of a layer definition: layers: { 'dojo/dojo ...