Search code examples
javascriptreactjsjsonfiltertree

How to recursively filter tree JSON in React/Javascript?


I need to filter this JSON tree data for a search (filter tree) functionality. The structure looks like this:

The Array filter > map is only going to the first level. How do I traverse up to the last level of child (filter should work on all levels after Customers) and filter accordingly using a string (includes logic)

{
   "path":"Customers",
   "sha":"Customers",
   "lazy":false,
   "type":"tree",
   "tree":[
      {
         "path":"Bob Rivers",
         "type":"tree",
         "sha":"Bob Rivers",
         "lazy":false,
         "tree":[
            {
               "path":"Services",
               "type":"tree",
               "sha":"Services",
               "lazy":true,
               "url":"http://localhost:3000/services",
               "tree":[
                  {
                     "path":"Service_X",
                     "type":"tree",
                     "sha":"Service_X",
                     "lazy":true,
                     "url":"http://localhost:3000/Service_X",
                     "tree":[
                        {
                           "lazy":true,
                           "path":"Service_X_child",
                           "mode":"040000",
                           "type":"tree",
                           "sha":"Service_X_child",
                           "url":"http://localhost:3000/Service_X_child",
                           "tree":[
                              {
                                 "lazy":true,
                                 "path":"ABC",
                                 "mode":"040000",
                                 "type":"blob",
                                 "sha":"ABC",
                                 "url":""
                              },
                              {
                                 "lazy":true,
                                 "path":"DEF",
                                 "mode":"040000",
                                 "type":"blob",
                                 "sha":"DEF",
                                 "url":""
                              }
                           ]
                        },
                        {
                           "lazy":true,
                           "path":"Service_X_child_2",
                           "mode":"040000",
                           "type":"tree",
                           "sha":"Service_X_child_2",
                           "url":"http://localhost:3000/Service_X_child_2"
                        }
                     ]
                  },
                  {
                     "path":"Service_Y",
                     "type":"tree",
                     "sha":"Service_Y",
                     "lazy":true,
                     "url":"http://localhost:3000/Service_Y"
                  }
               ],
            }
         ],
      }
   ],
}

Sample Input is if the search filter = "DEF" (path will be checked), the data will be reduced to this one

{
   "path":"Customers",
   "sha":"Customers",
   "lazy":false,
   "type":"tree",
   "tree":[
      {
         "path":"Bob Rivers",
         "type":"tree",
         "sha":"Bob Rivers",
         "lazy":false,
         "tree":[
            {
               "path":"Services",
               "type":"tree",
               "sha":"Services",
               "lazy":true,
               "url":"http://localhost:3000/services",
               "tree":[
                  {
                     "path":"Service_X",
                     "type":"tree",
                     "sha":"Service_X",
                     "lazy":true,
                     "url":"http://localhost:3000/Service_X",
                     "tree":[
                        {
                           "lazy":true,
                           "path":"Service_X_child",
                           "mode":"040000",
                           "type":"tree",
                           "sha":"Service_X_child",
                           "url":"http://localhost:3000/Service_X_child",
                           "tree":[
                              {
                                 "lazy":true,
                                 "path":"DEF",
                                 "mode":"040000",
                                 "type":"blob",
                                 "sha":"DEF",
                                 "url":""
                              }
                           ]
                        }
                     ]
                  }
               ],
            }
         ],
      }
   ],
}

I have tried the following solution/s but did not work: recursively filter json data for search bar

This one explicitly mentioned that flatting the JSON tree data to array did not solve his issue

https://www.geeksforgeeks.org/how-to-filter-object-array-based-on-attributes/


Solution

  •   const TreeNode = ({node , searchString}) => {
        if(!node.tree){
          return node.path.toLowerCase().includes(searchString.toLowerCase())? node:null
        }
    
        node.tree = node.tree.map(childNode => TreeNode(
          {
            node:childNode, searchString        
          }
        )).filter(n => n);
        return node.tree.length? node:null;
      }
     
    

    This recursive function solved my problem