如何根据同对象的locale值动态重命名Yup校验返回的错误键名
问题原因说明
你之前尝试的label()和transformKeys()都无法实现需求:
label()仅用于修改错误提示中展示的字段名称,不会改变错误对象的键名transformKeys()用于转换对象序列化输出的字段名,和错误返回结构无关,且回调无法获取同对象的其他字段值
可行实现方案
方案1:校验后统一转换错误结构(推荐)
无需修改原有校验逻辑,在校验捕获错误后统一对错误结构做格式化处理,代码示例如下:
// 原有校验Schema保持不变 const schema = yup.object().shape({ descriptions: yup.object().shape({ data: yup.array().of( yup.object().shape({ name: yup.string().required('required'), locale: yup.string().oneOf(['de', 'en']), }) ), }) }); // 校验逻辑 async function validateData(data) { try { await schema.validate(data, { abortEarly: false }); return { valid: true }; } catch (err) { const formattedErrors = { descriptions: { data: [] } }; err.inner.forEach(error => { // 解析错误路径,匹配descriptions.data[索引].name格式的错误 const pathMatch = error.path.match(/^descriptions\.data\[(\d+)\]\.name$/); if (pathMatch) { const index = Number(pathMatch[1]); const locale = data.descriptions.data[index].locale; // 初始化对应下标的错误对象 if (!formattedErrors.descriptions.data[index]) { formattedErrors.descriptions.data[index] = {}; } // 插入带locale后缀的错误键 formattedErrors.descriptions.data[index][`name_${locale}`] = error.message; } }); return { valid: false, errors: formattedErrors }; } }
方案2:自定义Test校验动态生成错误路径
通过在数组项的Schema层添加自定义校验方法,直接动态生成带locale后缀的错误路径:
const schema = yup.object().shape({ descriptions: yup.object().shape({ data: yup.array().of( yup.object().shape({ locale: yup.string().oneOf(['de', 'en']).required() // 移除原有的name字段校验,改为在object级test中实现 }).test('name-validate', function (item) { if (!item.name || typeof item.name !== 'string') { return this.createError({ // 动态拼接带locale后缀的错误字段名 path: `${this.path}.name_${item.locale}`, message: 'required' }); } return true; }) ) }) });
注意:该方案需要关闭
abortEarly配置才能收集所有错误,且如果后续需要新增其他带locale后缀的校验字段,需要对应修改test校验逻辑。
内容的提问来源于stack exchange,提问作者Merim
相关产品推荐
相关产品推荐

