NestJS中如何基于父类B的type属性验证子类A的content?
问题描述
在NestJS中使用class-validator进行嵌套对象验证时,类A作为类B中属性a的类型。需要在类A的content属性的自定义验证装饰器IsValidContent中,获取类B的type属性值,以此判断content是否符合对应类型规则:当type为X时验证content为Content1类型,为Y时验证为Content2类型。但当前代码尝试获取父类type属性失败,求可行的实现方法。
相关代码如下:
class Content1 {} class Content2 {} class A { @IsValidContent() content: Content1 | Content2; } class B { @Type(() => A) @ValidateNested({ each: true }) a: A; type: string; } export function IsValidContent(validationOptions?: ValidationOptions) { return (object: Object, propertyName: string) => { registerDecorator({ name: "isValidContent", target: object.constructor, propertyName, constraints: [], options: validationOptions, validator: { validate(value: any, args: ValidationArguments) { const type = args.object["type"]; // 无法获取父类的type属性 switch (type) { case "X": return isValidType(value, Content1); case "Y": return isValidType(value, Content2); default: return false; } }, }, }); } }
解决方案
问题根源
嵌套验证场景下,args.object指向的是当前被验证的类A实例,而type属性属于父类B的实例,因此直接通过args.object["type"]无法获取到目标值。
实现方法
利用ValidationArguments提供的root属性,它指向整个验证流程的根对象(也就是类B的实例),通过它可以直接读取type属性。同时补充isValidType的具体实现逻辑,使用class-validator和class-transformer的工具方法来判断类型是否匹配。
修改后的完整代码如下:
import { registerDecorator, ValidationArguments, ValidationOptions, validateSync } from 'class-validator'; import { plainToInstance } from 'class-transformer'; class Content1 {} class Content2 {} class A { @IsValidContent() content: Content1 | Content2; } class B { @Type(() => A) @ValidateNested({ each: true }) a: A; type: string; } // 辅助函数:验证值是否符合指定类的结构要求 function isValidType(value: any, targetClass: any): boolean { const instance = plainToInstance(targetClass, value); const errors = validateSync(instance); return errors.length === 0; } export function IsValidContent(validationOptions?: ValidationOptions) { return (object: Object, propertyName: string) => { registerDecorator({ name: "isValidContent", target: object.constructor, propertyName, constraints: [], options: validationOptions, validator: { validate(value: any, args: ValidationArguments) { // 通过root属性获取根对象(B的实例),进而拿到type const rootObj = args.root as B; const type = rootObj.type; switch (type) { case "X": return isValidType(value, Content1); case "Y": return isValidType(value, Content2); default: return false; } }, }, }); } }
注意事项
如果类B中的a是数组类型,args.root依然指向B的实例,不会受数组嵌套影响,因此上述代码同样适用。
内容的提问来源于stack exchange,提问作者Lang Minh Nguyên
相关产品推荐
相关产品推荐

