基于Joi Schema自动补全缺失叶子节点为null的通用方案需求
通用Joi Schema缺失字段补全方案(填充叶子节点为null)
核心思路是递归遍历Joi Schema的描述结构,对比输入数据的每一层节点,对缺失的字段、值为null/undefined的节点进行补全,直到最外层叶子节点,确保所有Schema定义的字段都存在,叶子节点默认填充为null。
完整代码实现
function populateMissingFields(data, schemaDesc) { // 处理基本类型(string/number/boolean) if (!schemaDesc || ['string', 'number', 'boolean'].includes(schemaDesc.type)) { return data != null ? data : null; } // 处理数组类型:若数据不是数组则返回空数组,否则递归处理每个元素 if (schemaDesc.type === 'array') { if (!Array.isArray(data)) { return []; } const itemSchema = schemaDesc.items; return data.map(item => populateMissingFields(item, itemSchema)); } // 处理对象类型:递归补全所有子字段 if (schemaDesc.type === 'object') { // 初始化结果对象,保留原数据的已有字段 const result = {...(data || {})}; const schemaKeys = schemaDesc.keys || {}; // 遍历Schema定义的所有key Object.entries(schemaKeys).forEach(([key, childSchema]) => { const currentValue = result[key]; // 递归补全当前key对应的value result[key] = populateMissingFields(currentValue, childSchema); }); return result; } // 其他未定义类型,返回原数据或null return data != null ? data : null; }
使用示例
1. 定义Joi Schema
const templateSchema = Joi.object({ studentData: Joi.object({ addr: Joi.object({ studentName: Joi.string().required(), studentAge: Joi.number().required() }).required(), education: Joi.object({ schoolName: Joi.string().required(), studentGrade: Joi.number().required() }).required() }).required() }).required();
2. 测试数据1(addr为null)
const apiData1 = { studentData: { addr: null, education: { schoolName: "TKM", studentGrade: 10 } } }; const schemaDesc = templateSchema.describe(); const result1 = populateMissingFields(apiData1, schemaDesc); console.log(result1);
输出结果:
{ studentData: { addr: { studentName: null, studentAge: null }, education: { schoolName: "TKM", studentGrade: 10 } } }
3. 测试数据2(缺失addr字段)
const apiData2 = { studentData: { education: { schoolName: "TKM", studentGrade: 10 } } }; const result2 = populateMissingFields(apiData2, schemaDesc); console.log(result2);
输出结果:
{ studentData: { addr: { studentName: null, studentAge: null }, education: { schoolName: "TKM", studentGrade: 10 } } }
方案优势
- 全场景覆盖:递归处理任意嵌套深度的Schema,包括对象缺失、对象为
null、多层嵌套叶子节点缺失等场景。 - 不依赖验证错误:直接基于Schema描述构建补全数据,避免Joi验证
abortEarly配置导致的报错遗漏问题。 - 灵活适配:支持基本类型、数组类型、对象类型的补全,可扩展支持更多Joi类型。
- 保留已有数据:仅补全缺失或无效的节点,原数据中已存在的有效值会被完整保留。
内容的提问来源于stack exchange,提问作者jos j
相关产品推荐
相关产品推荐

