ChrisPasa ChrisPasa - 6 months ago 11
JSON Question

JSON Hierarchical from Adjacency List

I have adjacency Data. with ID's and Parent ID's,

I trying to turn it into Hierarchical data, with nested JSON.

I have it working but when i have different objects with the same ID's but different parent ID's. The data get mixed up. Here is my Jfiddle.
https://jsfiddle.net/Chris1807/e6s8qom3/2/

var makeTree = (function() {
var isArray = function(obj) {
return Object.prototype.toString.call(obj) == "[object Array]";
};
var clone = function(obj) {
return JSON.parse(JSON.stringify(obj));
};
var buildTree = function(catalog, structure, start) {
return (structure[start] || []).map(function(nodeid, index) {
var record = catalog[nodeid];
var keys = structure[start][index];
var children = isArray(keys) ? keys.map(function(key) {
return buildTree(catalog, structure, key);
}) : buildTree(catalog, structure, keys);
if (children.length) {
record.children = children;
}
return record;
})
};
return function(flat) {
var catalog = flat.reduce(function(catalog, record) {
catalog[record.nodeid] = clone(record);
delete(catalog[record.nodeid].parentid);
return catalog;
}, {});
var structure = flat.reduce(function(tree, record) {
(tree[record.parentid] = tree[record.parentid] || []).push(record.nodeid);
return tree;
}, {});
return buildTree(catalog, structure, '#'); // this might be oversimplified.
}
}());


var flat = [{
nodeid: "123802475",
parent: "#",
parentid: "#",
text: "CONNECTOR",
typepart: "Component",
icon: "glyphicon glyphicon-leaf",
Count: 0,
state: null
}, {
nodeid: "123802476",
parent: "123802475",
parentid: "123802475",
text: "PLATE",
typepart: "SemiComponent",
icon: "glyphicon glyphicon-fire",
Count: 0,
state: null
}, {
nodeid: "90615593",
parent: "123802476",
parentid: "123802476",
text: "C3604",
typepart: "Material",
icon: "glyphicon glyphicon-grain",
Count: 0,
state: null
}, {
nodeid: "1396",
parent: "90615593",
parentid: "90615593",
text: "Copper",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "1762",
parent: "90615593",
parentid: "90615593",
text: "Iron",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "1061",
parent: "90615593",
parentid: "90615593",
text: "Lead",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "3281499",
parent: "90615593",
parentid: "90615593",
text: "Zinc (metal)",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "3402",
parent: "90615593",
parentid: "90615593",
text: "Tin",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "9505195",
parent: "123802476",
parentid: "123802476",
text: "e-plate Sn (electrodeposited Tin Coatings, bright and matt)",
typepart: "Material",
icon: "glyphicon glyphicon-grain",
Count: 0,
state: null
}, {
nodeid: "1995",
parent: "9505195",
parentid: "9505195",
text: "Carbon",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "3065",
parent: "9505195",
parentid: "9505195",
text: "Sulphur",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "1061",
parent: "9505195",
parentid: "9505195",
text: "Lead",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "3402",
parent: "9505195",
parentid: "9505195",
text: "Tin",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "749088",
parent: "123802476",
parentid: "123802476",
text: "e-plate Ni (bright) (electrodeposited Nickel bright)",
typepart: "Material",
icon: "glyphicon glyphicon-grain",
Count: 0,
state: null
}, {
nodeid: "1995",
parent: "749088",
parentid: "749088",
text: "Carbon",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "3112",
parent: "749088",
parentid: "749088",
text: "Nitrogen",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "3065",
parent: "749088",
parentid: "749088",
text: "Sulphur",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "2619",
parent: "749088",
parentid: "749088",
text: "Nickel",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "123802477",
parent: "123802475",
parentid: "123802475",
text: "INSULATOR",
typepart: "SemiComponent",
icon: "glyphicon glyphicon-fire",
Count: 0,
state: null
}, {
nodeid: "123799238",
parent: "123802477",
parentid: "123802477",
text: "Polypropylene",
typepart: "Material",
icon: "glyphicon glyphicon-grain",
Count: 0,
state: null
}, {
nodeid: "238",
parent: "123799238",
parentid: "123799238",
text: "Polypropylene",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "9999",
parent: "123799238",
parentid: "123799238",
text: "Misc., not to declare",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "123802478",
parent: "123802475",
parentid: "123802475",
text: "LOCK COVER",
typepart: "SemiComponent",
icon: "glyphicon glyphicon-fire",
Count: 0,
state: null
}, {
nodeid: "123795153",
parent: "123802478",
parentid: "123802478",
text: "Pa46-GF30",
typepart: "Material",
icon: "glyphicon glyphicon-grain",
Count: 0,
state: null
}, {
nodeid: "33167",
parent: "123795153",
parentid: "123795153",
text: "Polytetramethylene adipic acid dimide",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "23374",
parent: "123795153",
parentid: "123795153",
text: "GF-Fibre",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "883",
parent: "123795153",
parentid: "123795153",
text: "Antimonytrioxide",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "1432179",
parent: "123795153",
parentid: "123795153",
text: "Brominated Epoxy",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "1226985",
parent: "123795153",
parentid: "123795153",
text: "Pigment portion, not to declare",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "123802479",
parent: "123802475",
parentid: "123802475",
text: "CONTACT PIN",
typepart: "SemiComponent",
icon: "glyphicon glyphicon-fire",
Count: 0,
state: null
}, {
nodeid: "90615593",
parent: "123802479",
parentid: "123802479",
text: "C3604",
typepart: "Material",
icon: "glyphicon glyphicon-grain",
Count: 0,
state: null
}, {
nodeid: "1396",
parent: "90615593",
parentid: "90615593",
text: "Copper",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "1762",
parent: "90615593",
parentid: "90615593",
text: "Iron",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "1061",
parent: "90615593",
parentid: "90615593",
text: "Lead",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "3281499",
parent: "90615593",
parentid: "90615593",
text: "Zinc (metal)",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "3402",
parent: "90615593",
parentid: "90615593",
text: "Tin",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "749088",
parent: "123802479",
parentid: "123802479",
text: "e-plate Ni (bright) (electrodeposited Nickel bright)",
typepart: "Material",
icon: "glyphicon glyphicon-grain",
Count: 0,
state: null
}, {
nodeid: "1995",
parent: "749088",
parentid: "749088",
text: "Carbon",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "3112",
parent: "749088",
parentid: "749088",
text: "Nitrogen",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "3065",
parent: "749088",
parentid: "749088",
text: "Sulphur",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "2619",
parent: "749088",
parentid: "749088",
text: "Nickel",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "757906",
parent: "123802479",
parentid: "123802479",
text: "e-plate Au (functional) (electrodeposited functional Gold Coatings)",
typepart: "Material",
icon: "glyphicon glyphicon-grain",
Count: 0,
state: null
}, {
nodeid: "1995",
parent: "757906",
parentid: "757906",
text: "Carbon",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "3112",
parent: "757906",
parentid: "757906",
text: "Nitrogen",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "10153",
parent: "757906",
parentid: "757906",
text: "Gold",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "123802480",
parent: "123802475",
parentid: "123802475",
text: "BODY",
typepart: "SemiComponent",
icon: "glyphicon glyphicon-fire",
Count: 0,
state: null
}, {
nodeid: "73794193",
parent: "123802480",
parentid: "123802480",
text: "C5191",
typepart: "Material",
icon: "glyphicon glyphicon-grain",
Count: 0,
state: null
}, {
nodeid: "1396",
parent: "73794193",
parentid: "73794193",
text: "Copper",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "1762",
parent: "73794193",
parentid: "73794193",
text: "Iron",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "1061",
parent: "73794193",
parentid: "73794193",
text: "Lead",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "3281499",
parent: "73794193",
parentid: "73794193",
text: "Zinc (metal)",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "3402",
parent: "73794193",
parentid: "73794193",
text: "Tin",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "2835",
parent: "73794193",
parentid: "73794193",
text: "Phosphorus",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "9999",
parent: "73794193",
parentid: "73794193",
text: "Misc., not to declare",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "9505195",
parent: "123802480",
parentid: "123802480",
text: "e-plate Sn (electrodeposited Tin Coatings, bright and matt)",
typepart: "Material",
icon: "glyphicon glyphicon-grain",
Count: 0,
state: null
}, {
nodeid: "1995",
parent: "9505195",
parentid: "9505195",
text: "Carbon",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "3065",
parent: "9505195",
parentid: "9505195",
text: "Sulphur",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "1061",
parent: "9505195",
parentid: "9505195",
text: "Lead",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "3402",
parent: "9505195",
parentid: "9505195",
text: "Tin",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "749088",
parent: "123802480",
parentid: "123802480",
text: "e-plate Ni (bright) (electrodeposited Nickel bright)",
typepart: "Material",
icon: "glyphicon glyphicon-grain",
Count: 0,
state: null
}, {
nodeid: "1995",
parent: "749088",
parentid: "749088",
text: "Carbon",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "3112",
parent: "749088",
parentid: "749088",
text: "Nitrogen",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "3065",
parent: "749088",
parentid: "749088",
text: "Sulphur",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}, {
nodeid: "2619",
parent: "749088",
parentid: "749088",
text: "Nickel",
typepart: "Substance",
icon: "glyphicon glyphicon-asterisk",
Count: 0,
state: null
}];

Answer

The solution is to use real unique keys in the catalog object, to avoid that you overwrite previously stored objects. As you wrote that nodeid values are guaranteed to be unique when they have children, you could just prefix any nodeid with the parentid to make your catalog keys unique.

So, only three lines need to change:

  var record = catalog[start + '/' + nodeid];

and:

  catalog[record.parentid + '/' + record.nodeid] = clone(record);
  delete(catalog[record.parentid + '/' + record.nodeid].parentid);

That's it.

As a performance improvement I would suggest not to use JSON text conversion to copy objects, but to use Object.assign instead:

var clone = function(obj) {
    return Object.assign({}, obj);
};