Convert a JSON object into a new format with a nested hierarchy

The JSON object below is currently formatted as follows:

{
  "id": "jsonid",
  "attributes": {
    "personName": {
      "id": "name1",
      "group": "1.1"
    },
    "age": {
      "id": "age1",
      "group": "1.2.1"
    },
    "height": {
      "id": "height1",
      "group": "1.2.2.1"
    }
  }
}

In order to transform the attribute based on its group property into a hierarchical structure, it should be converted to the following format:

{
  "id": "jsonid",
  "attributes": {
    "group1": {
      "id": "group1",
      "attributes": {
        "group1.1": {
          "id": "group1.1",
          "attributes": {
            "personName": {
              "id": "name1"
            }
          }
        },
        "group1.2": {
          "id": "group1.2",
          "attributes": {
            "group1.2.1": {
              "id": "group1.2.1",
              "attributes": {
                "age": {
                  "id": "age1"
                }
              }
            },
            "group1.2.2": {
              "id": "group1.2.2",
              "attributes": {
                "group1.2.2.1": {
                  "id": "1.2.2.1",
                  "attributes": {
                    "height": {
                      "id": "height1"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

A function has been developed to handle all unique group values and break them into their possible combinations. For this specific JSON object, the potential combinations are: ["1", "1.1", "1.2", "1.2.1", "1.2.2", "1.2.2.1"]. The function iterates through these values:

allPossible.map((groupId, index, array) => {
      createGroups(groupId, index, array);
});

The function used for this purpose is detailed below:

const createGroups = (groupId, index, array) => {
      let groupObject = {
        [groupId]: {
          id: groupId,
          attributes: {},
        },
      };
      if (array[index + 1]) {
        //If next element exists
        if (groupId.length === array[index + 1].length) {
          //To Check if the element should be in the same level 
//e.g. group ids 1.1 and 1.2 should be under group id 1
          let groupIdPrevious = array[index - 1];
          groupObject[groupIdPrevious].attributes = createGroups(
            array[index + 1],
            index + 1,
            array
          );
        }
        groupObject[groupId].attributes = createGroups(
          array[index + 1],
          index + 1,
          array
        );
      }
      return groupObject;
    };

Answer №1

Upon obtaining the various combinations, the subkeys can be generated using a method similar to this:

const info = { "identifier": "jsonid", "details": {
    "personName": { "identifier": "name1", "grouping": "1.1" },
    "age": { "identifier": "age1", "grouping": "1.2.1" },
    "height": { "identifier": "height1", "grouping": "1.2.2.1" } } }

let output = { ...info, details: {} }

for (let code in info.details)
{
  const value = info.details[code]
  let grouping = 'group' + value.grouping, attribute = output.details
  const fetchAttributes = id => (attribute[id] ??= { id, attributes: {} }).attributes
  
  for (let i = grouping.indexOf('.'); i > 0; i = grouping.indexOf('.', i + 1))
  {
    attribute = fetchAttributes(grouping.slice(0, i))
  }
  
  fetchAttributes(grouping)[code] = { identifier: value.identifier }
}

console.log( output )

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

Counter cannot be accessed once it has been updated

When I click a button, an interval should start. The issue is that I'm unable to access the value of counter. The goal is for the interval to stop when the counter reaches 5. Here's an example: let interval = null; const stateReducer = (state, ...

What is the process of uploading files using Ajax?

Can anyone help me with submitting a form using ajax that contains images? I have this code snippet which logs an object called "FormData" in the console, but I'm not sure how to properly use it or retrieve it. Is this the correct approach? $("#form_ ...

Using `getElementById` within the Vue.js `mounted` lifecycle hook can sometimes return null

Every time I attempt to retrieve the contents of an id using document.getElementById, I keep receiving a value of null. Below is a snippet of the code: <input-layout v-if="edit" label="Status" class="grayout"> &l ...

Is there a way to detect when the browser's back button is clicked?

As I work on supporting an e-commerce app that deals with creating and submitting orders, a user recently discovered a loophole wherein they could trigger an error condition by quickly pressing the back button after submitting their order. To address this ...

Tips for dynamically populating a mat-table dataSource

While working with backend data streaming, I encountered an issue where trying to push an event to dataSource resulted in an error stating that dataSource is not defined. Can anyone provide guidance on how to dynamically add data to a materialize table? s ...

Display a dynamic variable within React's HTML code

const fetchTime = () => { const currentDate = new Date(); const currentTime = currentDate + ' ' + currentDate.getHours() + ":" + currentDate.getMinutes() + ":" + currentDate.getSeconds(); return {currentTime}; } export default fun ...

What is the best way to incorporate a class creation pattern in Typescript that allows one class to dynamically extend any other class based on certain conditions?

As I develop a package, the main base class acts as a proxy for other classes with members. This base class simply accepts a parameter in its constructor and serves as a funnel for passing on one class at a time when accessed by the user. The user can spe ...

I am struggling to display the data fetched by Next.js on the page

I am struggling to display the data from the first file in my tanstack table or as a string within the HTML, even though I can see it in a console.log when grabbed by axios. The tanstack table worked fine with hardcoded data. In the console image provided, ...

What is the method to have VIM recognize backticks as quotes?

Currently working in TypeScript, I am hoping to utilize commands such as ciq for modifying the inner content of a template literal. However, it appears that the q component of the command only recognizes single and double quotation marks as acceptable ch ...

Notify users with a prompt when a modal or popup is closed on Google Chrome extensions

I have developed a Google Chrome extension for setting timers and receiving alerts. Currently, the alert only goes off when the extension is open, but I want it to fire even when the extension is closed. This extension currently requires the window to be ...

A Flume agent is extracting information from Kafka and archiving it in parquet structure

Can anyone provide guidance on setting up a Flume agent to ingest data from a Kafka topic and store it in Parquet format? I've been unable to find a straightforward solution for directly writing data in Parquet. ...

"Have you ever wondered how the router object in express.js is seamlessly integrated with app.use(), considering that it only accepts

I am curious about the process of how the router object in express.js is passed to app.use(), which typically only accepts callbacks. Since router is an object of express, I am trying to understand why app.use() does not throw an error even though it req ...

I have developed a function that adds up price values, but for some reason it is always lagging one step behind

I am facing an issue with my React container that has add and subtract functions. These functions are triggered whenever a user clicks on '+' or '-' spans, to calculate the total 'price' of three different 'products' ...

Is there a tool available that can convert the string "foo:blah" into JSON format?

My goal is to transform a human-readable list like the following: Enabled: Yes Server: example.com Port: 8080 Authenticated Proxy Enabled: 1 ... into a sanitized JSON object as shown below: { "Enabled": "Yes", "Server": "example.com", "Port" ...

JavaScript does not recognize jsPDF

After importing the jsPDF library, I attempted to export to PDF but encountered a JavaScript error stating that jsPDF is not defined. I tried various solutions from similar posts but none of them seemed to work for me. You can find the fiddle here: https ...

Casting user-defined data types to JSON objects can be achieved using the `jason.simple` library

I'm facing an issue with type casting a user-defined data type, USERS, into a JSON Object. When I tried using .toString() to convert Users into a String, the output was unexpected and incorrect. I then considered converting it into a JSON Object and r ...

Using Google script to send JSON data to PandaDoc API

I am currently working on generating a new document in PandaDoc using the Google Script editor. Although everything seems to be functioning well (the document is successfully created with the correct name and template), I'm encountering an issue with ...

Pass along computed style data to the parent component in Vue.js

I am relatively new to VueJS and currently in the process of exploring its features. One specific issue I am facing on my website involves a TopBar component that includes both the logo and the menu. <template> <div id="topBar"> <div ...

Is it possible to use "/path/{?}" in a path when working with Node.js?

I am new to node.js and I'm working on creating a route that will verify the authorization of all users when the specified endpoint begins with /api. I've learned that an optional value can be indicated using ? like {_id?}, but is it possible to ...

The resolution of Angular 8 resolver remains unresolved

I tried using console.log in both the constructor and ngOnInit() of Resolver but for some reason, they are not being logged. resolve:{serverResolver:ServerResolverDynamicDataService}}, console.log("ServerResolverDynamicDataService constructor"); console ...