You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现员工列表与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: "校验通过" };
}

代码说明

  1. 规则预处理:把Schema中的员工规则转换成Map和合法字段集合,大幅提升字段校验时的查找效率,避免重复遍历Schema。
  2. 递归校验逻辑:
    • 优先检查多余属性:只要发现Schema未定义的字段,立即返回错误。
    • 其次检查必填属性:确保所有标记为必填的字段都存在。
    • 最后校验类型:区分基础类型和嵌套员工数组类型,数组类型会递归校验内部的每个员工对象,保证嵌套结构的合法性。
  3. 提前终止机制:遍历员工列表时,只要遇到首个校验失败的情况就立即返回结果,符合需求中“返回首个校验失败案例”的要求。

内容的提问来源于stack exchange,提问作者alchuang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 06:35:31