如何实现员工列表与Schema的递归校验函数?
员工数据校验函数实现方案
问题背景
给定包含嵌套结构的员工列表(其中reports属性为员工对象的嵌套数组),示例如下:
const employees = [ { name: 'alice', title: "ceo", salary: 100, reports: [{ name: "bob", title: "cfo", salary: 10, reports: [{ name: 'zorp', title:"controller", salary: 40 }], }], }, // 更多员工对象... ]
同时提供用于定义员工字段校验规则的Schema对象:
const schema = { employee: [ { name: "name", required: true, type: "string" }, { name: "title", required: true, type: "string" }, { name: "salary", required: false, type: "number" }, { name: "remote", required: false, type: "boolean" }, { name: "reports", required: false, type: "array:employee" }, ] }
校验规则
- 所有校验通过时,返回
{ ok: true, message: "校验通过" } - 若必填属性缺失,返回
{ ok: false, message: "${name} 不存在" } - 若属性类型不符合要求,返回
{ ok: false, message: "${name} 属性类型无效,应为${type}" } - 若对象包含Schema未定义的属性,返回
{ ok: false, message: "属性 ${name} 不属于Schema定义" }
需要实现validate函数,返回首个校验失败的结果。
实现代码
function validate(employees, schema) { // 将员工规则转为Map,快速查找字段规则 const employeeRuleMap = new Map(schema.employee.map(rule => [rule.name, rule])); // 生成合法字段集合,用于检查多余属性 const validFields = new Set(employeeRuleMap.keys()); // 递归校验单个员工对象 function checkEmployee(emp) { // 1. 检查是否存在Schema未定义的属性 for (const field of Object.keys(emp)) { if (!validFields.has(field)) { return { ok: false, message: `属性 ${field} 不属于Schema定义` }; } } // 2. 检查必填属性是否存在 for (const rule of schema.employee) { if (rule.required && !(rule.name in emp)) { return { ok: false, message: `${rule.name} 不存在` }; } } // 3. 校验各属性类型 for (const [field, rule] of employeeRuleMap) { // 非必填属性未提供则跳过 if (!(field in emp)) continue; const value = emp[field]; const expectedType = rule.type; // 处理嵌套员工数组的情况 if (expectedType === 'array:employee') { if (!Array.isArray(value)) { return { ok: false, message: `${field} 属性类型无效,应为array:employee` }; } // 递归校验数组内的每个员工 for (const subEmp of value) { const checkResult = checkEmployee(subEmp); if (!checkResult.ok) return checkResult; } } else { // 基础类型校验 const actualType = typeof value; // 严格匹配类型(注意:typeof null为object,若需支持null需额外处理) if (actualType !== expectedType) { return { ok: false, message: `${field} 属性类型无效,应为${expectedType}` }; } } } return { ok: true, message: "校验通过" }; } // 遍历所有员工,逐个校验 for (const emp of employees) { const result = checkEmployee(emp); if (!result.ok) return result; } return { ok: true, message: "校验通过" }; }
代码说明
- 规则预处理:把Schema中的员工规则转换成Map和合法字段集合,大幅提升字段校验时的查找效率,避免重复遍历Schema。
- 递归校验逻辑:
- 优先检查多余属性:只要发现Schema未定义的字段,立即返回错误。
- 其次检查必填属性:确保所有标记为必填的字段都存在。
- 最后校验类型:区分基础类型和嵌套员工数组类型,数组类型会递归校验内部的每个员工对象,保证嵌套结构的合法性。
- 提前终止机制:遍历员工列表时,只要遇到首个校验失败的情况就立即返回结果,符合需求中“返回首个校验失败案例”的要求。
内容的提问来源于stack exchange,提问作者alchuang
相关产品推荐
相关产品推荐

