Search code examples
javascriptarraysjsonjavascript-objectsnested-loops

List all nested properties with their full path in the containing object


I have some arrays of names stored in nested JSON like this:

{
    "groupZ": {
        "names": [
            "Steve",
            "Henry"
        ]
    },
    "groupY": {
        "groupA": {
            "names": [
                "Laura"
            ]
        },
        "groupB": {
            "names": [
                "Alice",
                "Bob",
                "Neil"
            ]
        }
    },
    "groupX": {
        "groupC": {
            "groupD": {
                "names": [
                    "Steph"
                ]
            }
        },
        "groupE": {
            "names": [
                "Aaron",
                "Dave"
            ]
        }
    }
}

I'm trying to figure out how to generate a list of all names, prepended with the full group path for each name, so it ends up like this:

  • groupZ - Steve
  • groupZ - Henry
  • groupY - groupA - Laura
  • groupY - groupB - Alice
  • groupY - groupB - Bob
  • groupY - groupB - Neil
  • groupX - groupC - groupD - Steph
  • groupX - groupE - Aaron
  • groupX - groupE - Dave

The group names will be unique at each level, but other than that could be called anything. I know I will need to recursively call a function which stops when it finds a "names" array, passing through a string to add to the prepend with each recursion, but having real trouble. Here's my code so far:

var sPrepend = '';
function buildList(Groups, lastGroupName){

    for(var thisGroupName in Groups) {
        var thisGroup = Groups[thisGroupName];

        if(!thisGroup.names){
            sPrepend += (' - ' + thisGroupName);
            buildList(thisGroup, thisGroupName);
        }
        if(thisGroup.names){
            thisGroup.names.forEach(function(name){
                console.log(sPrepend, ' - ', name);
                //build the list item here.
            });
        }
    }
}
buildList(oGroups, '');

It's got me stumped as I'm not able to change the JSON structure but I'm sure it is possible. Thanks anyone who can help!


Solution

  • This works for me:

    function buildList(group, accum, key) {
    
        // default helper parameters
        accum = accum || [];
        key = key || '';
    
        if (group.names) {  // add each name
            group.names.forEach(function(name) {
                accum.push(key + name);
            });
        } else {            // or recurse on each key
            Object.getOwnPropertyNames(group).forEach(function(gname) {
                buildList(group[gname], accum, key + gname + ' - ');
            });
        }
    
        return accum;
    }
    
    var list = buildList(oGroups);