Manipulating JSON by writing a new array and adding data as child elements

I have a JSON that looks like this:

var json = [{
  "name": "0xcd963fe5b4d9de5380130d6c6b6cfb5d3b903b1f",
  "parent": "null"
}, {
  "name": "0xe8f84d8ad5850d66bd289ce3199753c35f4cbf40",
  "parent": "0xcd963fe5b4d9de5380130d6c6b6cfb5d3b903b1f"
}, {
  "name": "0x8fa01b60f503a3873c1b02ef351112f57cdd818e",
  "parent": "0xe8f84d8ad5850d66bd289ce3199753c35f4cbf40"
}, {
  "name": "0x753a018eca49f1b1e8b46b88d6a7b449478740e0",
  "parent": "0xcd963fe5b4d9de5380130d6c6b6cfb5d3b903b1f"
}]

I am attempting to rewrite it using Javascript into a new JSON structure with the following order:

var json = [{
  "name": "0xcd963fe5b4d9de5380130d6c6b6cfb5d3b903b1f",
  "parent": "null",
  "children": [{
    "name": "0x753a018eca49f1b1e8b46b88d6a7b449478740e0",
    "parent": "0xcd963fe5b4d9de5380130d6c6b6cfb5d3b903b1f"
  }, {
    "name": "0xe8f84d8ad5850d66bd289ce3199753c35f4cbf40",
    "parent": "0xcd963fe5b4d9de5380130d6c6b6cfb5d3b903b1f",
    "children": [{
      "name": "0x8fa01b60f503a3873c1b02ef351112f57cdd818e",
      "parent": "0xe8f84d8ad5850d66bd289ce3199753c35f4cbf40"
    }]
  }]
}]

In this new structure, children are created and nested under their parent object. Each name is unique, the first object has no parent ("null"), and some objects may not have any children ("null" or an empty array []).

I'm not very familiar with Javascript and I'm unsure of how to achieve this. I've tried different loops without success, such as:

json.forEach(function(link) {
    var parent = link.parent = nodeByName(json,link.parent),
        child = link.children = nodeByName(json,link.children);
    if (parent.children) parent.children.push(child);
    else parent.children = [child];
  });

This results in:

[{
  "name": "0xcd963fe5b4d9de5380130d6c6b6cfb5d3b903b1f",
  "parent": {
    "name": "null",
    "children": [{}]
  },
  "children": {}
}, {
  "name": "0xe8f84d8ad5850d66bd289ce3199753c35f4cbf40",
  "parent": {
    "name": "0xcd963fe5b4d9de5380130d6c6b6cfb5d3b903b1f",
    "children": [{}, {}]
  },
  "children": {}
}, {
  "name": "0x8fa01b60f503a3873c1b02ef351112f57cdd818e",
  "parent": {
    "name": "0xe8f84d8ad5850d66bd289ce3199753c35f4cbf40",
    "children": [{}]
  },
  "children": {}
}, {
  "name": "0x753a018eca49f1b1e8b46b88d6a7b449478740e0",
  "parent": {
    "name": "0xcd963fe5b4d9de5380130d6c6b6cfb5d3b903b1f",
    "children": [{}, {}]
  },
  "children": {}
}]

Answer №1

If you're looking to handle multiple nested levels of children, one approach is to utilize the reduce() method along with a recursive function:

function retrieveChildren (nodeName, data) {
  return data
    .filter(({ parent }) => parent === nodeName)
    .map(item => ({...item, children: retrieveChildren(item.name, jsonData)}));
}

const resultObject = jsonData.reduce((accum, {name, parent}) => {
  if (parent === "null") {
    accum[name] = { name, parent, children: retrieveChildren(name, jsonData) };
  }
  return accum;
}, {});

const resultArray = Object.values(resultObject);

Answer №2

Thank you to @blex for pointing out that this function achieved exactly what I needed. Much appreciated!

This code is based on the following answer: Converting a flat array into a tree array in JavaScript

function transformListIntoTree(list) {
    var map = {}, node, roots = [], i;
    for (i = 0; i < list.length; i += 1) {
        map[list[i].name] = i;
    }
    for (i = 0; i < list.length; i += 1) {
        node = list[i];
        if (node.parent !== "null") {
            var parent = list[map[node.parent]];
            if (!parent.children) {
              parent.children = [];
            }
            parent.children.push(node);
        } else {
            roots.push(node);
        }
    }
    return roots;
}

var result = transformListIntoTree(json)

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

The controller in AngularJS does not accurately reflect changes made by toggling a checkbox

My query involves a checkbox. <input ng-model="defaultAssigneeCheckbox" type="checkbox"/> <p>{{defaultAssigneeCheckbox}}</p> <button type="submit">Save</button> The paragraph underneath accurately displays and updates the c ...

What is the best way to utilize various arguments from an array to build an execl() function call in C?

I am currently working with a string array in C called args[] - now I am wondering how to utilize this list of arguments to create a proper call to execl()? For example, if the array includes: {"/bin/ls","ls","-a","-l"} ...how can I ultimately generate ...

Conditional statement based on the background color

Despite researching various topics on using background colors in if statements, I have yet to find a satisfactory solution. Whether I define an element as a variable beforehand or use rgb/rgba values, my code does not produce the desired results; it always ...

Display a pop-up message following the successful addition of an item to the cart across

Running a WooCommerce webshop, I want a popup to appear when customers click on the "Add to Cart" button. The code I have written works perfectly in Google Chrome but doesn't function in Safari due to page reload issues. I suspect that the problem li ...

Populate an array in Java with N elements containing a specific string character (?)

Is there a way to generate the following string in Java efficiently? ?, ?, ?, ?, ? In PHP, it can be achieved using: $s = implode(", ", array_fill(0, 5, "?")); In Python, it can be done with: s = ", ".join(["?"] * 5) In Swift, the code looks like thi ...

Is there a universal method to disregard opacity when utilizing jQuery's clone() function across different web browsers?

I've encountered a situation where I need to allow users to submit a new item to a list within a table, and have it smoothly appear at the top of the list. While using DIVs would make this task easier, I am working with tables for now. To achieve thi ...

Applying conditional logic within computed properties results in a failure to update

I have two different fiddles: Fiddle A and Fiddle B (both using Vuejs version 2.2.4) In my code, I have a computed property that can be changed programmatically by utilizing the get and set methods. Expectations for the Computed Property: If the def ...

"Strategies for identifying the presence of a return value or null in jQuery AJAX

Currently, I am utilizing a jQuery post ajax request to perform an action. The page 'submit.php' sends back a JSON value, and sometimes if there is a fatal error it returns nothing. I am struggling to determine whether the ajax call returns a va ...

Guide to sending a post request with parameters in nuxt.js

I am trying to fetch data using the fetch method in Nuxt/Axios to send a post request and retrieve specific category information: async fetch() { const res = await this.$axios.post( `https://example.com/art-admin/public/api/get_single_cat_data_an ...

The system encountered an error due to the absence of a defined Google or a MissingKeyMapError from the

Currently, I am developing a component that includes ng-map functionality by following the guidance in this tutorial. <div class="content-pane" map-lazy-load="https://maps.google.com/maps/api/js" map-lazy-load-params="{{$ctrl.googleMapsUrl}}"> & ...

Find all the components associated with a specific name in Vue, even if they are nested within other components

One interesting feature in my app is the sidebar: https://i.sstatic.net/7Z9IN.png The code for the tree item component looks like this : <!-- tree item template --> <script type="text/x-template" id="tree-item-template"> <div> ...

Steps for assigning certain elements in an array to null and then repositioning them to the end of the array

Although I am aware that utilizing an ArrayList would make this task much simpler, I am limited to using arrays for now. Here is the method I have come up with: public boolean remove(String name) { int temp = 0; for (int i = 0; i < counter; i+ ...

Struggling to find a solution to adjust an Angular directive

I am attempting to create a functionality where, upon clicking a button, the user can select one of two images displayed and make the selected image draggable. Currently, my code displays two images with only one being draggable. I am struggling to impleme ...

"Unlock the power of Passport.js: A guide to leveraging async rendering for email templates

Currently, my setup involves running Express with Sequelize/MariaDB and Passport.js to handle user authentication. Everything seems to be working smoothly except for the activation email that needs to be sent out after a user signs up. Despite having the ...

What is causing the crash in p5.js when I use this function to add objects to an array?

I'm currently working on an evolution simulation app that involves reproducing organisms with a health level above 75%. After reproduction, their health is reduced by half. However, I'm encountering an issue where my app crashes in p5.js for reas ...

Combining two arrays into a single associative array in Actionscript 3

How can I create an array in ActionScript 3.0 that combines the keys of one array with the values of another array? Here is my incorrect code. Package import omitted. public class myPages extends Sprite { protected var pageNames:Array = []; prote ...

Acquiring arrays from random files

Modified for better understanding. Although file IO allows us to access and manipulate file elements, my question goes beyond that. Imagine we have multiple files, each containing only one list with some data in it. import os def make_bars(self): fo ...

Circular reference in Angular/TypeScript

I encountered a circular dependency issue in my Angular project and tried various solutions, including exporting all dependent classes from a "single file" as suggested here. Unfortunately, this approach did not work for me. I then explored other solutions ...

Transform a group of strings into ObjectId using Mongo, then proceed to delete them

I am currently working with an array of strings containing ids. My goal is to convert these strings into ObjectIds and then use them to delete records from the collection. arrOfStr = ['6346ed8f0c2437c710321c4e','6346ed8f0c2437c710321c4f&apos ...

What is the method for revealing elements with a click?

Every time I click on a button, the number 1 is displayed. However, upon clicking again, an error occurs stating that "push" is not a function. It appears that index 1 in the button array has been pushed into state.num, causing the type of state.num to cha ...