带有自定义错误消息的类验证器关系验证

Ali*_*ion 5 typescript class-validator nestjs

所以我正在构建一个 API,用户在请求正文中向我们提供,type可以是valuetypeCNIC, EMAIL, MOBILE

现在基于type我必须验证该值,例如是否EMAIL有效或是否MOBILE有效等。

正如我们所看到的,该value字段依赖于type验证它的字段。

我需要一种方法来使用class-validator validationPipe.

Ali*_*ion 7

所以一开始我很快打开文档并开始查找高级用法,我开始知道自定义装饰器肯定会对我有帮助,并且使用下面的示例确实如此。

validate-value-by-type.decorator.ts

import {
  registerDecorator,
  ValidationOptions,
  ValidationArguments,
  isEmail,
} from 'class-validator';
import { CA_DetailsTypes } from './models';

export function ValidateByAliasType(
  property: string,
  validationOptions?: ValidationOptions,
) {
  // eslint-disable-next-line @typescript-eslint/ban-types
  return function (object: Object, propertyName: string) {
    registerDecorator({
      name: 'validateByAliasType',
      target: object.constructor,
      propertyName: propertyName,
      constraints: [property],
      options: validationOptions,
      validator: {
        validate(value: any, args: ValidationArguments) {
          const [relatedPropertyName] = args.constraints;
          const relatedValue = (args.object as any)[relatedPropertyName];
          if (relatedValue === CA_DetailsTypes.EMAIL) {
            return isEmail(value) && value.length > 5 && value.length <= 99;
          }
          if (relatedValue === CA_DetailsTypes.CNIC) {
            return value.length === 13;
          }
          if (relatedValue === CA_DetailsTypes.MOBILE) {
            return value.length === 11;
          }
          if (relatedValue === CA_DetailsTypes.TXT) {
            return value.length > 3 && value.length <= 99;
          }
          return false;
        },
      },
    });
  };
}
Run Code Online (Sandbox Code Playgroud)

client.request.dto.ts

import { ApiProperty } from '@nestjs/swagger';
import { IsEnum, IsNotEmpty } from 'class-validator';

export enum CA_DetailsTypes {
  'CNIC' = 'CNIC',
  'MOBILE' = 'MOBILE',
  'EMAIL' = 'EMAIL',
  'TXT' = 'TXT',
}

export class CA_FetchDetails_DTO {
  @ApiProperty({
    example: 'MOBILE',
    type: 'enum',
    enum: CA_DetailsTypes,
  })
  @IsNotEmpty()
  @IsEnum(CA_DetailsTypes)
  type: CA_DetailsTypes;

  @ApiProperty({ example: '03070000002' })
  @ValidateByAliasType('type')
  value: string;
}
Run Code Online (Sandbox Code Playgroud)

因此,通过上面的示例,我成功地能够value通过进行验证type,但仍然无法根据 自定义错误消息type

因此,经过一天的研究,我失去了所有的希望,决定使用另一个库来进行这个复杂的验证,我这样做了,但该库有一个缺点,我最终回到了,经过class-validator大量研究后,我发现了一个的方式来自定义错误消息type

所以这里是基于自定义错误消息的代码type,我曾经defaultMessage()自定义过它。

validate-value-by-type.decorator.ts

import {
  registerDecorator,
  ValidationOptions,
  ValidationArguments,
  isEmail,
} from 'class-validator';
import { CA_DetailsTypes } from './models';

export function ValidateByAliasType(
  property: string,
  validationOptions?: ValidationOptions,
) {
  // eslint-disable-next-line @typescript-eslint/ban-types
  return function (object: Object, propertyName: string) {
    registerDecorator({
      name: 'validateByAliasType',
      target: object.constructor,
      propertyName: propertyName,
      constraints: [property],
      options: validationOptions,
      validator: {
        validate(value: any, args: ValidationArguments) {
          const [relatedPropertyName] = args.constraints;
          const relatedValue = (args.object as any)[relatedPropertyName];
          if (relatedValue === CA_DetailsTypes.EMAIL) {
            return isEmail(value) && value.length > 5 && value.length <= 99;
          }
          if (relatedValue === CA_DetailsTypes.CNIC) {
            return value.length === 13;
          }
          if (relatedValue === CA_DetailsTypes.MOBILE) {
            return value.length === 11;
          }
          if (relatedValue === CA_DetailsTypes.TXT) {
            return value.length > 3 && value.length <= 99;
          }
          return false;
        },
        defaultMessage(args?: ValidationArguments) {
          const [relatedPropertyName] = args.constraints;
          const relatedValue = (args.object as any)[relatedPropertyName];
          switch (relatedValue) {
            case CA_DetailsTypes.EMAIL:
              return 'Please enter valid email!';

            case CA_DetailsTypes.MOBILE:
              return 'Please enter valid mobile!';

            case CA_DetailsTypes.CNIC:
              return 'Please enter valid CNIC!';

            default:
              return 'Invalid value!';
          }
        },
      },
    });
  };
}
Run Code Online (Sandbox Code Playgroud)

终于完成了!