【问题标题】:How to validate child DTO conditionally with class-validator?如何使用类验证器有条件地验证子 DTO?
【发布时间】:2022-04-09 19:03:47
【问题描述】:

我正在尝试使用类验证器有条件地验证嵌套 DTO,但 @ValidateIf 似乎没有正确应用并始终验证嵌套类。

我有以下 DTO:

export class SuperAdminStoreDto extends StoreDto {

    @IsOptional()
    @IsBoolean()
    readonly payments: boolean;

    @ValidateIf(object => object.payments)
    @ValidateNested({ each: true })
    @Type(() => PaymentDetails)
    readonly payment_details: PaymentDetails[];
}

class PaymentDetails {

    @IsNumberString()
    @IsNotEmpty()
    readonly min: string;

    @IsNumberString()
    @IsNotEmpty()
    readonly max: string;

    @IsNumberString()
    @IsNotEmpty()
    readonly percentage: string;
}

假设正在验证的对象是:

{
    "payments": false,
    "payment_details": {
        "min": "1"
    }
}

我应该没有错误,因为我已经使用以下标志设置了验证器:

{
  whitelist: true,
  forbidNonWhitelisted: true,
  forbidUnknownValues: true,
  validationError: {
   target: false,
  }
}

我希望验证器不允许子对象存在并引发错误。

【问题讨论】:

  • 我遇到了完全相同的问题,我不知道如何解决。目前我确定 ValidateIf 不适用于 ValidateNested。有条件嵌套验证的解决方案吗?

标签: class-validator class-transformer


【解决方案1】:

我使用的一个选项是创建自定义装饰器来验证嵌套对象,因为自定义装饰器与 @ValidateIf() 一起使用

type Class<T> = { new (...args: any[]): T };
        
export function ValidateDtoArray(dto: Class<any>, validationOptions?: ValidationOptions) {
  return function (object: unknown, propertyName: string) {
    registerDecorator({
      name: 'validateDto',
      target: (object as any).constructor,
      propertyName: propertyName,
      options: validationOptions,
      validator: {
        async validate(value: unknown, args: ValidationArguments) {
          if (!isArray(value)) return false;
          for (let i = 0; i < (value as any[]).length; i++) {
            const array_value = (value as any[])[i];
            if(typeof array_value !== 'object') return false;
            const validation_errors = await validate(plainToClass(dto, array_value as Record<string, unknown>);
            if (validation_errors.length > 0) return false;
          }
          return true;
        },
        defaultMessage(validationArguments?: ValidationArguments) {
          return `Can only be of type ${dto.name}[]`;
        },
      },
    });
  };
}

你的代码就变成了

export class SuperAdminStoreDto extends StoreDto {

    @IsOptional()
    @IsBoolean()
    readonly payments: boolean;

    @ValidateIf(object => object.payments)
    @ValidateDtoArray(PaymentDetails)
    @Type(() => PaymentDetails)
    readonly payment_details: PaymentDetails[];
}

【讨论】:

    猜你喜欢
    • 2021-05-25
    • 1970-01-01
    • 2022-11-20
    • 1970-01-01
    • 1970-01-01
    • 2023-02-13
    • 2021-03-08
    • 2022-12-30
    • 1970-01-01
    相关资源
    最近更新 更多