简体   繁体   English

从嵌套 JSON 对象数组中的任何给定子级的直接父级获取值?

[英]Get values from immediate parent for any given child in array of nested JSON objects?

Here is a sample of my JSON.这是我的 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.我希望能够在所有 leaveRequests 中按 id 搜索并获取员工的姓名和姓氏。

If I pass id "3000" I would like to be able to get an object ["name": "Jon", "surname": "Smith"]如果我通过 id "3000" 我希望能够获得 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?我已经尝试实施解决方案: 如何在嵌套 json Object 的数组中获取子 ID 的直接父 ID?

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:我必须将我的 JSON 结构重组为:

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?如何在所有 leaveRequests 中按 id 搜索并从直系父母那里获取员工的姓名和姓氏?

I'd suggest walking through the object recursively, and returning if we find an object with a leaveRequest property.我建议递归遍历 object,如果我们找到带有leaveRequest属性的 object 则返回。

Once we find this we'll strip off the leaveRequest and return the rest of the object.一旦我们找到这个,我们将去掉 leaveRequest 并返回 object 的 rest。

 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 }

Here is an answer using object-scan :这是使用object-scan的答案:

 .as-console-wrapper {max-height: 100%;important: top 0}
 <script type="module"> import objectScan from 'https://cdn.jsdelivr.net/npm/object-scan@18.3.0/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免责声明:我是对象扫描的作者

Part of the challenge is the data is oddly shaped, with objects containing single-element arrays and arrays containing single-keyed objects.部分挑战是数据形状奇怪,对象包含单元素 arrays 和 arrays 包含单键对象。 I'd start by reshaping the data to something more rational (using an assumption that the data isn't recursive -- employees don't contain other employees).我首先将数据重塑为更合理的东西(假设数据不是递归的——员工不包含其他员工)。

// create a flat array of employees [ employeeA, employeeB, ...
const employees = data[0].employees.map(object => object.employee[0]);

With that, the way to go from a leaveRequest id to the containing employee is to build an index.这样,从leaveRequest id到包含员工的 go 的方法是建立一个索引。 Here, another assumption is that leaveRequest ids are unique.这里,另一个假设是 leaveRequest id 是唯一的。

// create an index { leaveIdX: employeeC, leaveIdY: employeeD, ...
const leaveRequestIndex = employees.reduce((index, employee) => {
  employee.leaveRequest.forEach(request => index[request.id] = employee);
  return index;
}, {});

That provides an O(1) lookup from leaveRequest to employee, like this...这提供了从 leaveRequest 到员工的 O(1) 查找,就像这样......

// given someLeaveRequestId, get the containingEmployee
const containingEmployee = leaveRequestIndex[someLeaveRequestId];

Testing on the OP data...对 OP 数据进行测试...

 // create a flat array of employees [ { employee }, { employee }, ... const employees = data()[0].employees.map(object => object.employee[0]); // create an index { leaveId: { employee }, leaveId: { employee }, ... const leaveRequestIndex = employees.reduce((index, employee) => { employee.leaveRequest.forEach(request => index[request.id] = employee); return index; }, {}); // test it: which employee has leave request 3001? const employee = leaveRequestIndex[3001]; const { name, surname } = employee; console.log(name, surname); function data() { return [{ "employees": [ { "employee": [ { "name": "Jon", "surname": "Smith", "leaveRequest": [ { "id": "3000", "approver": "Terry" }, { "id": "3001", "approver": "Larry" } ] }], }, { "employee": [ { "name": "Mike", "surname": "Jones", "leaveRequest": [ { "id": "1700", "approver": "Mary" } ] }, ] } ] }]; }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM