Convert delimited string into hierarchical JSON with JQuery
Asked Answered
R

1

17

I have an array of strings that describe the parent/child relationship by being delimited with dashes. So, if Bob's boss was Jim and Jim's boss was Fred, Bob's entry in the array would be "Fred-Jim-Bob" and Jim's entry would be "Fred-Jim." I don't have the ability to change the way the data is coming in so I was looking for help as far as the best way of turning these values into JSON similar to this:

{
    "name": "Fred",
    "children": {
        "name": "Jim",
        "children": {
            "name": "Bob"
        }
    }
}

Any help would be greatly appreciated. Thanks.

Rhondarhondda answered 3/6, 2011 at 21:13 Comment(2)
can you give an example of the input string? also, does it go down infinite levels, or is it limited to 3?Berryberryhill
Well it would be an array of strings like the ones shown above. So for the json I mentioned above the array might be: var emp = new Array("Fred-Jim","Fred","Fred-Jim-Bob"); and yes it could be more or less than 3.Rhondarhondda
S
36
var input = ["Fred-Jim-Bob", "Fred-Jim", "Fred-Thomas-Rob", "Fred"];
var output = [];
for (var i = 0; i < input.length; i++) {
    var chain = input[i].split("-");
    var currentNode = output;
    for (var j = 0; j < chain.length; j++) {
        var wantedNode = chain[j];
        var lastNode = currentNode;
        for (var k = 0; k < currentNode.length; k++) {
            if (currentNode[k].name == wantedNode) {
                currentNode = currentNode[k].children;
                break;
            }
        }
        // If we couldn't find an item in this list of children
        // that has the right name, create one:
        if (lastNode == currentNode) {
            var newNode = currentNode[k] = {name: wantedNode, children: []};
            currentNode = newNode.children;
        }
    }
}

output JSONifies as:

[{
    "name": "Fred",
    "children": [{
        "name": "Jim",
        "children": [{
            "name": "Bob",
            "children": []
        }]
    }, {
        "name": "Thomas",
        "children": [{
            "name": "Rob",
            "children": []
        }]
    }]
}]
Sanctity answered 3/6, 2011 at 21:39 Comment(5)
The example input happens to have strings that go up to 3 levels, but you're welcome to add more. Try loading the example and making one of the strings say "Fred-Jim-Bob-Mark". You'll see it works fine, too. Mathematical infinity it probably won't handle, but anything within reasonable bounds when browser memory is concerned should work.Sanctity
Yes, I'm using this to parse out data for a company's org chart, so I don't need INFINITE levels, but prepared for more than 3.Rhondarhondda
Works great, is there anyway you can add comments this code? I'm getting lost when debugging where you're setting currentNode = currentNode[k] = currentNode[k].children or currentNode = newNode.children which I believe is one of the most important steps in this algorithm.Lithium
I know this is super old now but this isn't working for me. Isn't 'K' out of scope by the time that you try and reuse it in the final if statement?Jawbone
Still works fine for me (just tested in a current browser's JS console). In JS var is hoisted, so no, it won't be out of scope. If you're switching to let or const or using some language other than JS, or babel or a similar thing that transforms your JS, perhaps that is breaking it?Sanctity

© 2022 - 2024 — McMap. All rights reserved.