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

基于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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 08:01:24