Home > Net >  Get values from immediate parent for any given child in array of nested JSON objects?
Get values from immediate parent for any given child in array of nested JSON objects?

Time:07-29

Here is a sample of my JSON.

const data = [{
   "employees": [ 
      {         
         "employee": [
            {
               "name": "Jon",
               "surname": "Smith",
               "leaveRequest": [
                  {
                     "id": "3000",
                     "approver": "Terry"
                  }
               ]
            }],
      },
      {
         "employee": [
            {
               "name": "Mike",
               "surname": "Jones",
               "leaveRequest": [
                  {
                     "id": "1700",
                     "approver": "Mary"
                  }
               ]
            },
         ]
      }
   ]
}];

I want to be able to search by id across all leaveRequests and get the employee's name and surname.

If I pass id "3000" I would like to be able to get an object ["name": "Jon", "surname": "Smith"]

I've tried implementing the solution from: How to get immediate parent Id of the child id in array of nested json Object?

This is what I've tried:

const findEmployee = (arr, id) => {
   for (let i = 0; i < arr.length; i  ) {
      if (arr[i].id === id) {
         return [];
      } 
      else if (arr[i].employee && arr[i].employee.length) {
         const t = findEmployee(arr[i].employee, id);

         if (t !== false) {
         if (t.length == 0) 
            t.push({"name": arr[i].name, "surname": arr[i].surname});
            return t;
         }
      }
   }
   return false;
};

console.log(findEmployee(data, "3000"))

But the solution in that thread relies on each child node having the same key 'children' which wouldn't work in my scenario. I'd have to restructure my JSON structure to be:

employee
    employee
       employee
          id

And this doesn't make sense in my scenario. How can I search by id across all leaveRequests and get the employee's name and surname from the immediate parent?

CodePudding user response:

I'd suggest walking through the object recursively, and returning if we find an object with a leaveRequest property.

Once we find this we'll strip off the leaveRequest and return the rest of the object.

const data = [{ "employees": [ { "employee": [ { "name": "Jon", "surname": "Smith", "leaveRequest": [ { "id": "3000", "approver": "Terry" } ] }], }, { "employee": [ { "name": "Mike", "surname": "Jones", "leaveRequest": [ { "id": "1700", "approver": "Mary" } ] }, ] } ] }]; 
 
function findRequest(input, id) {
    if (input.leaveRequest && input.leaveRequest[0].id == id) {
        // Return everything bar the leave request...
        return (({ leaveRequest, ...obj}) => obj)(input);
    }
    for(let k in input) {
        if (input[k] && typeof(input[k]) === 'object') {
            let leaveRequest = findRequest(input[k], id);
            if (leaveRequest) return leaveRequest;
        }
    }
}

let ids = [1700, 3000];
ids.forEach(id => console.log('id: ', id, '\nrequest:', findRequest(data, id)));
.as-console-wrapper { max-height: 100% !important; }

CodePudding user response:

Here is an answer using object-scan:

.as-console-wrapper {max-height: 100% !important; top: 0}
<script type="module">
import objectScan from 'https://cdn.jsdelivr.net/npm/[email protected]/lib/index.min.js';

const data = [{ employees: [{ employee: [{ name: 'Jon', surname: 'Smith', leaveRequest: [{ id: '3000', approver: 'Terry' }] }] }, { employee: [{ name: 'Mike', surname: 'Jones', leaveRequest: [{ id: '1700', approver: 'Mary' }] }] }] }];

const find = objectScan(['[*].employees[*].employee[*].leaveRequest[*].id'], {
  abort: true, // abort after first result
  filterFn: ({ value, context }) => value === context, // find the correct id
  rtn: ({ parents }) => parents[2] // return the correct node
});

console.log(find(data, '3000'));
// => { name: 'Jon', surname: 'Smith', leaveRequest: [ { id: '3000', approver: 'Terry' } ] }
</script>

Disclaimer: I'm the author of object-scan

  • Related