如何正确合并两个JOI基础校验schema 解决Schema can only contain plain objects报错
Joi合并多个基础Schema的正确实现方案
Error: Schema can only contain plain objects 报错的核心原因是:
baseAddressSchema是Joi的Schema实例,不是普通的字段定义对象,直接使用展开运算符...无法获取其内部的纯对象格式字段配置,传入.keys()方法时就会触发参数类型校验失败。
推荐方案:使用.concat()方法合并Schema
Joi官方提供了concat方法专门用于合并两个同类型的Schema实例,不需要手动提取字段,天然支持规则继承和覆盖,实现代码如下:
export const contactSchema = baseValidationSchema // 第一步:合并地址校验Schema的所有规则 .concat(baseAddressSchema) // 第二步:追加当前Schema独有的自定义字段校验规则 .keys({ email: validateEmail(), firstName: validateName(), lastName: validateName(), phone: validatePhone(), spamFlag: validateBoolean() });
注意事项
- 合并的优先级由调用顺序决定:后合并的Schema规则会覆盖前序Schema的同名字段规则,如果需要自定义字段优先级高于
baseAddressSchema的同名字段,保持上面的写法即可;如果需要地址字段优先级更高,可以把.keys()调用移到.concat()前面。 - 该方法仅支持合并同类型的Schema,比如两个都是
Joi.object()类型的Schema,这也是你的业务场景下的默认情况。
特殊场景备选方案:提取Schema字段为纯对象
如果确实需要手动操作字段配置,可以通过.describe()方法获取Schema的结构化描述,再提取字段对象合并,该方案稳定性低于concat,仅推荐特殊场景使用:
// 提取baseAddressSchema的所有字段配置为纯对象 const addressFieldConfig = baseAddressSchema.describe().keys; export const contactSchema = baseValidationSchema.keys({ ...addressFieldConfig, email: validateEmail(), firstName: validateName(), lastName: validateName(), phone: validatePhone(), spamFlag: validateBoolean() });
内容的提问来源于stack exchange,提问作者flow24
相关产品推荐
相关产品推荐

