'iterate through complex nested json array javascript

nested json structure

Json Structure:

{
"id": "30080",
        "dataelements": {
    "Name": "abc",
        },
        "children": [
            {
                "id": "33024",
                "dataelements": {
                    "Name": "a",
                    },
                "children": [
                    {
                        "id": "33024",
                        "dataelements": {
                            "Name": "b"

                            },
                        "children": [
                            {
                                "id": "33024",
                                "dataelements": {
                                    "Name": "z"
                                    },
                                "children": []
                            }
                        ]
                    }
                ]
            },
            {
                "id": "4800",
                "dataelements": {
                    "Name": "d"
                    },
                "children": [
                    {
                        "id": "4800",
                        "dataelements": {

.........................

I have my nested json data as shown in the image. For every child object, I create a node model. A child object can have additional child objects inside it.

 if (ele == "dataelements")
{
    var categoryNode = new NodeModel(
    {
        label: row.dataelements.Name,
        icons: [{ iconName: 'product'}],
        grid: row[ele] 
    });
}

if(ele == "children")
{
    var subCategoryNode;
    var subCategoryIndex = 1;
    for (var i = 0, len = row.children.length; i<len; i++) 
    {
        subCategoryNode = new NodeModel(
        {
            label: row.children[i].dataelements.Name,
            icons: [{
            iconName: '3dpart' }],
            grid: row.children[i].dataelements                             
        });

        categoryNode.addChild(subCategoryNode);
    }
}

This code handles only one level of child nodes. How do I check for the inner children when I don't know exactly how many child levels are nested inside?



Solution 1:[1]

A quick run down on recursive functions and a gotcha to look out for

  • Recursive functions are great for nested data
  • They call themselves for each iteration of the input until it hits a base case
  • They can be tricky to wrap your head around at first
  • Recursive functions can hit the call stack limit if used poorly or the input is monstrous in size
  • Look out for variables used in the recursive calls, use let keyword to tell javascript to set the variable in the current scope

The Solution

Let's assume your JSON has been validated and this is the structure in the example below. If I want to iterate through all elements in the JSON, I want to use a recursive call to make it neat, and simple to debug and simple to build on.

Here is an example of iterating through your given example JSON to print out an exploded view.

How to use the below code

  • Copy the recursiveSearch function
  • Call the recursiveSearch function passing in your JSON
  • Modify it to your needs, I gave you something to build on

CODE

    var someJson = {"id": "30080","dataelements": {"Name": "abc"},"children": [{"id": "33024","dataelements": {"Name": "a"},"children": [{"id": "33024","dataelements": {"Name": "b"},"children": [{"id": "33024","dataelements": {"Name": "z"},"children": []}]}]}, {"id": "4800","dataelements": {"Name": "d"},"children": []}]};

    //we set level to 0 (optional variable) this means we can omit it in the inital call for neat code
    function recursiveScan(json, level=0)
    {
        //we store all of the output in a log and keep a track of the level to determine indenting
        var log = "";
        var indent = "";

        //based on the current level of the recursion, we indent the text to make it readable
        for (let i=0; i<level; i++)
        {
            indent += "&emsp;&emsp;";
        }

        //avoid any bad json or invalid data by checking if the name and id is null
        if(json.dataelements.Name != null && json.id != null)
        {
            //we know there is a valid element, write the name and id
            log += indent + "ID: " + json.id + "<br>";
            log += indent + "Name: " + json.dataelements.Name + "<br>";

            //if there is any children
            if(json.children.length > 0)
            {
                //just for neatness, lets draw the paranthesis
                log += indent + "{" + "<br>";

                //increase the level
                level++;

                //for each child, recursively call this function to get the next level of children if available
                for(let t=0; t<json.children.length; t++)
                {
                    log += recursiveScan(json.children[t], level);
                }

                //we are dropping our recursion level now, getting ready to return;
                level--;
                //close the paranthesis for neatness
                log += indent + "}" + "<br>";
            }
        }

        //return the final log
        return log;
    }

    //now lets test the code
    document.write(recursiveScan(someJson));

The above code produces

    ID: 30080
    Name: abc
    {
    ??ID: 33024
    ??Name: a
    ??{
    ????ID: 33024
    ????Name: b
    ????{
    ??????ID: 33024
    ??????Name: z
    ????}
    ??}
    ??ID: 4800
    ??Name: d
    }

Now a simple run-down without all the noise

    function recursiveScan(json)
    {
        if(json.dataelements.Name != null && json.id != null)
        {
            //here you have access to id and dataelements

            if(json.children.length > 0)
            {
                for(let t=0; t<json.children.length; t++)
                {
                    //here you have access to each child as json.children[t]
                    //you could do the logic for the current child

                    //then pass the current child to the recursive function
                    recursiveScan(json.children[t]);
                }
            }
        }
        return true;
    }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1