如何使用Yup校验对象数组并移除校验未通过的无效字段?
问题原因
Yup 的 cast 方法仅负责类型转换、以及根据 stripUnknown 配置移除 schema 未定义的额外字段,不会自动移除 schema 中已定义、但校验规则不通过的字段,这是当前代码没有达到预期效果的核心原因。
实现方案
你可以先全量校验收集所有失败字段的路径,再手动清理对应字段,具体实现代码如下:
// 你的原有 schema 无需修改 const schema = Yup.object().shape({ id: Yup.string().nullable(false), country: Yup.string().trim().nullable(false), firstname: Yup.string().trim().nullable(false), lastname: Yup.string().trim().nullable(false), email: Yup.string().trim().nullable(false).email(), phoneNum: Yup.string() .trim() .test("phone", "", (value) => isPossiblePhoneNumber(`+1${value}`)) }); const schemaArr = Yup.array().of(schema); // 核心处理逻辑 const processInput = async (input) => { let invalidFields = []; try { // 全量校验收集所有错误,必须开启abortEarly: false await schemaArr.validate(input, { abortEarly: false, stripUnknown: true }); } catch (err) { // 提取所有校验失败的字段路径,格式如[0].email、[1].phoneNum invalidFields = err.inner.map(e => e.path); } // 先执行cast移除未知字段 const castedArr = schemaArr.cast(input, { stripUnknown: true }); // 遍历移除每个对象中校验失败的字段 return castedArr.map((item, index) => { const cleaned = { ...item }; invalidFields.forEach(path => { if (path.startsWith(`[${index}].`)) { const field = path.split('.')[1]; delete cleaned[field]; } }); return cleaned; }); }; // 调用示例 const sanitization = await processInput(你的待校验数组);
可选调整
如果你需要的是仅保留所有字段都校验通过的对象,直接过滤掉存在校验失败字段的对象,可在上述返回逻辑前追加过滤规则:
return castedArr.map(/* 上述清理逻辑 */) // 仅保留字段数量和schema定义一致的对象,说明无字段被删除 .filter(item => Object.keys(item).length === Object.keys(schema.fields).length);
内容的提问来源于stack exchange,提问作者MarksCode
相关产品推荐
相关产品推荐

