繁体   English   中英

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

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

这是我的 JSON 的样本。

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

我希望能够在所有 leaveRequests 中按 id 搜索并获取员工的姓名和姓氏。

如果我通过 id "3000" 我希望能够获得 object ["name": "Jon", "surname": "Smith"]

我已经尝试实施解决方案: 如何在嵌套 json Object 的数组中获取子 ID 的直接父 ID?

这是我尝试过的:

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"))

但是该线程中的解决方案依赖于每个子节点具有相同的键“孩子”,这在我的场景中不起作用。 我必须将我的 JSON 结构重组为:

employee
    employee
       employee
          id

这在我的场景中没有意义。 如何在所有 leaveRequests 中按 id 搜索并从直系父母那里获取员工的姓名和姓氏?

我建议递归遍历 object,如果我们找到带有leaveRequest属性的 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 }

这是使用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>

免责声明:我是对象扫描的作者

部分挑战是数据形状奇怪,对象包含单元素 arrays 和 arrays 包含单键对象。 我首先将数据重塑为更合理的东西(假设数据不是递归的——员工不包含其他员工)。

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

这样,从leaveRequest id到包含员工的 go 的方法是建立一个索引。 这里,另一个假设是 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;
}, {});

这提供了从 leaveRequest 到员工的 O(1) 查找,就像这样......

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

对 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