使用Join验证固定数组



由于这是一种不同类型的"阵列验证";。

从本质上讲,我想从函数参数中获取rest参数的动态集合,并根据RESTapi的模式对它们进行验证。例如:

@Validation(Schema.update)
public async update(id: string, model: Model) => { }

然后使用我的decorator拦截函数调用,并根据提供的模式执行验证:


export function Validation(schema: ObjectSchema) {
return (target: any, propName: string | symbol, descriptor: PropertyDescriptor): void => {
const originalMethod = descriptor.value!;
descriptor.value = function (...rest: any[]): ApiResult {
const { error } = schema.validate({ ...rest });
if (error) {
console.error(error.message);
return new ErrorApiResult({ statusCode: 400, message: error?.message });
}
return originalMethod.apply(this, arguments);
};
};
}

目前,我想注意的是,这非常有效,除了我必须创建这样的验证模式:

export const Schema = {
update: Joi.object({
0: Joi.string(),
1: ModelSchema,
}),
}

这方面的主要问题是,验证错误消息Join生成的标签字段如0.user.name而不是model.user.name等。

相反,我想写上面的端点模式,比如:

export const Schema = {
update: Joi.object({
id: Joi.string().required(),
model: ModelSchema,
}),
}

但我不知道该怎么做。看看Joi.array((,它似乎只被设计用于处理对象的集合,而不是严格的参数数组。

编辑:我曾尝试使用.label()方法来更改错误消息中的标签,但如果错误在于嵌套键,则此方法不起作用。例如,如果我的id参数没有正确验证,它就会工作,但如果我的ModelSchema未能对子属性进行验证,它就不会正确显示。它在错误消息中仍然显示为"1.user.name"

我无法解决在特定数组上定义Joi验证的问题,但我可以使用我的Joi模式元数据来构建一个满足Joi模式的自定义对象,如下所示:

export function Validation(schema: ObjectSchema) {
return (target: any, propName: string | symbol, descriptor: PropertyDescriptor): void => {
const originalMethod = descriptor.value!;
descriptor.value = function (...rest: any[]): ApiResult {
const validationObject: any = {};
const keys: string[] = Array.from((schema as any)._ids._byKey.keys());
for (let i = 0; i < keys.length; i++) {
validationObject[keys[i]] = rest[i];
}
const { error } = schema.validate(validationObject);
if (error) {
console.error(error.message);
return new ErrorApiResult({ statusCode: 400, message: error?.message });
}
return originalMethod.apply(this, arguments);
};
};
}

我必须破坏Typescript的类型安全性才能在运行时访问这些字段。所以这不是非常理想。但是,只要验证对象中键的顺序与我正在验证的函数中参数的顺序匹配,它就可以工作。

最新更新