btc4cash
btc4cash

Reputation: 325

JSON manipulation, rewriting a new array appending data as children

I have a JSON that is :

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

I'm trying to using Javascript to rewrite this into a new JSON that would be ordered like:

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

Children would be created and nested to their parent object. Each name is unique, first object have no parent ("null"), and it's possible an object don't have children ("null" or empty array []).

I'm not used to javascript and I'm not sure how exactly I can achieve that, I tried various loop but not working, 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];
  });

But this result as :

[{
  "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": {}
}]

Upvotes: 0

Views: 71

Answers (2)

btc4cash
btc4cash

Reputation: 325

As @blex mentioned in a comment, this function did exactly what I needed to achieve. Thanks a lot!

This is an adaptation of this answer: Build tree array from flat array in javascript

function list_to_tree(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 res = list_to_tree(json)

Upvotes: 0

sgmonda
sgmonda

Reputation: 2719

You can use reduce(), combined with a recursive function (to support many nested children levels):

function getChildren (name, items) {
  return items
    .filter(({ parent }) => parent === name)
    .map(item => ({...item, children: getChildren(item.name, json)}));
}

const resultAsObject = json.reduce((accum, {name, parent}) => {
  if (parent === "null") {
    accum[name] = { name, parent, children: getChildren(name, json) };
  }
  return accum;
}, {});

const resultAsArray = Object.values(resultAsObject);

Upvotes: 2

Related Questions