'Extracting all nested IDs

I have below JSON for example where I need to extract all categories Id from the last subcategory if its not empty. For instance: On below JSON I need Ids like mens-apparel-ricky inside last categories object but if this categories was empty I like to extract the last ID like womens-new-arrivals. Basically it should be the list of all these ID's extracted. Thanks in Advance

    "categories": [{
        "id": "featured",
        "name": "NEW ARRIVALS",
        "categories": [{
            "id": "featured-new-arrivals",
            "name": "New Arrivals",
            "categories": [{
                "id": "mens-new-arrivals",
                "name": "Mens",
                "categories": []
            }, {
                "id": "womens-new-arrivals",
                "name": "Womens",
                "categories": [{
                    "id": "mens-apparel-ricky",
                    "name": "Relaxed",
                    "categories": []
                }, {
                "id": "new-arrivals-kids",
                "name": "Kids",
                "categories": []
            }, {
                "id": "new-arrivals-accessories",
                "name": "Accessories",
                "categories": []
            }]
        }, {
            "id": "collections",
            "name": "Featured",
            "categories": [{
                "id": "spring-shop",
                "name": "Spring Shop",
                "categories": [{
                    "id": "spring-shop-mens",
                    "name": "Spring Shop Men's",
                    "categories": []
                }, {
                    "id": "spring-shop-womens",
                    "name": "Spring Shop Women's",
                    "categories": []
                }]
            }, {
                "id": "the-festival-shop",
                "name": "The Festival Shop",
                "categories": [{
                    "id": "mens-festival-shop",
                    "name": "Mens Festival Shop",
                    "categories": []
                }, {
                    "id": "womens-festival-shop",
                    "name": "Womens Festival Shop",
                    "categories": []
                }]
            }, {
                "id": "buddha-collections",
                "name": "The Icons Shop",
                "categories": [{
                    "id": "buddha-collections-men",
                    "name": "Mens",
                    "categories": []
                }, {
                    "id": "buddha-collections-women",
                    "name": "Womens",
                    "categories": []
                }]
            }, {
                "id": "all-black",
                "name": "All Black Everything",
                "categories": []
            }]
        }]
    }, {
        "id": "denim",
        "name": "DENIM",
        "categories": [{
            "id": "denim-view-all",
            "name": "Shop All Denim",
            "categories": [{
                "id": "denim-view-all-mens",
                "name": "Mens Denim",
                "categories": []
            }, {
                "id": "denim-view-all-womens",
                "name": "Womens Denim",
                "categories": []
            }, {
                "id": "denim-view-all-kids",
                "name": "Kids Denim",
                "categories": []
            }]
        }, {
            "id": "denim-collections",
            "name": "Featured",
            "categories": [{
                "id": "denim-collections-signature-stitch",
                "name": "Big T & Super T Stitch",
                "categories": []
            }, {
                "id": "denim-collections-lighten-up",
                "name": "Light Wash Denim",
                "categories": []
            }, {
                "id": "dark-wash-denim",
                "name": "Dark Wash Denim",
                "categories": []
            }]
        }]
    }]
}

This is what I have tried but being new to coding getting difficult to get list form this complex structure.


    var rootCategories = (jsonData.categories);
   
    for (var i=0; i < rootCategories.length; i++)
    {
         var firstChild = (jsonData.categories[i].categories);
         for (var j=0; j < firstChild.length; j++)
        {
            if ((firstChild[j].categories[j].length != 0)) {
                catId = firstChild[j].categories[j].id
                 console.log(catId);
            }
        }
    }


Solution 1:[1]

Below is one possible way to achieve the target.

Code Snippet

// recursive method to get "id"s
const getIds = arr => (
  arr.flatMap(                // iterate using ".flatMap()" to avoid nesting
    ({id, categories}) => {   // de-structure to directly access "id" & "categories"
      if (                    // if "categories" is not empty, recurse to next level
        Array.isArray(categories) &&
        categories.length > 0
      ) {
        return getIds(categories);
      } else {                // if it is empty, simply return the id
        return id;
      }
    }
  )
);

const rawData = {
  "categories": [{
    "id": "featured",
    "name": "NEW ARRIVALS",
    "categories": [{
      "id": "featured-new-arrivals",
      "name": "New Arrivals",
      "categories": [{
        "id": "mens-new-arrivals",
        "name": "Mens",
        "categories": []
      }, {
        "id": "womens-new-arrivals",
        "name": "Womens",
        "categories": [{
          "id": "mens-apparel-ricky",
          "name": "Relaxed",
          "categories": []
        }, {
          "id": "new-arrivals-kids",
          "name": "Kids",
          "categories": []
        }, {
          "id": "new-arrivals-accessories",
          "name": "Accessories",
          "categories": []
        }]
      }, {
        "id": "collections",
        "name": "Featured",
        "categories": [{
          "id": "spring-shop",
          "name": "Spring Shop",
          "categories": [{
            "id": "spring-shop-mens",
            "name": "Spring Shop Men's",
            "categories": []
          }, {
            "id": "spring-shop-womens",
            "name": "Spring Shop Women's",
            "categories": []
          }]
        }, {
          "id": "the-festival-shop",
          "name": "The Festival Shop",
          "categories": [{
            "id": "mens-festival-shop",
            "name": "Mens Festival Shop",
            "categories": []
          }, {
            "id": "womens-festival-shop",
            "name": "Womens Festival Shop",
            "categories": []
          }]
        }, {
          "id": "buddha-collections",
          "name": "The Icons Shop",
          "categories": [{
            "id": "buddha-collections-men",
            "name": "Mens",
            "categories": []
          }, {
            "id": "buddha-collections-women",
            "name": "Womens",
            "categories": []
          }]
        }, {
          "id": "all-black",
          "name": "All Black Everything",
          "categories": []
        }]
      }]
    }, {
      "id": "denim",
      "name": "DENIM",
      "categories": [{
        "id": "denim-view-all",
        "name": "Shop All Denim",
        "categories": [{
          "id": "denim-view-all-mens",
          "name": "Mens Denim",
          "categories": []
        }, {
          "id": "denim-view-all-womens",
          "name": "Womens Denim",
          "categories": []
        }, {
          "id": "denim-view-all-kids",
          "name": "Kids Denim",
          "categories": []
        }]
      }, {
        "id": "denim-collections",
        "name": "Featured",
        "categories": [{
          "id": "denim-collections-signature-stitch",
          "name": "Big T & Super T Stitch",
          "categories": []
        }, {
          "id": "denim-collections-lighten-up",
          "name": "Light Wash Denim",
          "categories": []
        }, {
          "id": "dark-wash-denim",
          "name": "Dark Wash Denim",
          "categories": []
        }]
      }]
    }]
  }]
};

console.log(getIds(rawData.categories));
.as-console-wrapper { max-height: 100% !important; top: 0 }

Explanation

Inline comments added in the snippet above.

Solution 2:[2]

If you're not afraid of reference loops (shouldn't technically happen in a serialized REST response) you can try recurring function as the simplest way to achieve this

function getIDs(node, isRoot = false) {
  if (!node.categories.length) // if I understood your question correctly, you don't want parents to be printed out, otherwise just check for isRoot instead
    return isRoot || console.log(node.id);
  // with above you won't access non-existent id of the root collection
  // because it will stop checking after first true statement
  for (const category of categories)
    getIDs(category);
}

getIDs(collection, 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 jsN00b
Solution 2 waszqba