Проверка вложенных объектов с помощью валидатора классов и nestjs

Я пытаюсь проверить вложенные объекты с помощью валидатора классов и NestJS. Я уже пробовал следовать этому потоку, используя декоратор @Type из class-transform, и мне не повезло. Вот что у меня есть:

DTO:

class PositionDto {
  @IsNumber()
  cost: number;

  @IsNumber()
  quantity: number;
}

export class FreeAgentsCreateEventDto {

  @IsNumber()
  eventId: number;

  @IsEnum(FinderGamesSkillLevel)
  skillLevel: FinderGamesSkillLevel;

  @ValidateNested({ each: true })
  @Type(() => PositionDto)
  positions: PositionDto[];

}

Я также использую встроенный канал проверки nestjs, это мой начальный этап:

async function bootstrap() {
  const app = await NestFactory.create(ServerModule);
  app.useGlobalPipes(new ValidationPipe());
  await app.listen(config.PORT);
}
bootstrap();

Он отлично работает для других свойств, только массив объектов не работает.


person Leonardo Emilio Dominguez    schedule 14.12.2018    source источник
comment
Я только что поместил ваш код в пустой образец проекта, и, похоже, он мне подходит. Какое конкретное значение не работает? Каковы ваши ожидания? Если вы, например, поместите "positions": [{"other": true}] в свое тело, оно отклонится с 400. Однако positions: [] - допустимое значение.   -  person Kim Kern    schedule 14.12.2018
comment
Я ожидаю, что если вы попробуете positions: [1], выдаст ошибку   -  person Leonardo Emilio Dominguez    schedule 14.12.2018


Ответы (2)


Вы ожидаете, что positions: [1] выбросит 400, но вместо этого это принято.

Согласно этой проблеме Github, это, похоже, ошибка в класс-валидатор. Если вы передадите примитивный тип (boolean, string, _4 _, ...) или array вместо объекта, он примет ввод как действительный, хотя этого не должно быть.


Я не вижу никакого стандартного обходного пути, кроме создания настраиваемого декоратора проверки:

import { registerDecorator, ValidationOptions, ValidationArguments } from 'class-validator';

export function IsNonPrimitiveArray(validationOptions?: ValidationOptions) {
  return (object: any, propertyName: string) => {
    registerDecorator({
      name: 'IsNonPrimitiveArray',
      target: object.constructor,
      propertyName,
      constraints: [],
      options: validationOptions,
      validator: {
        validate(value: any, args: ValidationArguments) {
          return Array.isArray(value) && value.reduce((a, b) => a && typeof b === 'object' && !Array.isArray(b), true);
        },
      },
    });
  };
}

а затем используйте его в своем классе dto:

@ValidateNested({ each: true })
@IsNonPrimitiveArray()
@Type(() => PositionDto)
positions: PositionDto[];
person Kim Kern    schedule 14.12.2018

для меня я мог бы проверить вложенный объект с помощью 'class-transformer'

import { Type } from 'class-transformer';

полный пример:

import {
  MinLength,
  MaxLength,
  IsNotEmpty,
  ValidateNested,
  IsDefined,
  IsNotEmptyObject,
  IsObject,
  IsString,
} from 'class-validator';
import { Type } from 'class-transformer';

class MultiLanguageDTO {
  @IsString()
  @IsNotEmpty()
  @MinLength(4)
  @MaxLength(40)
  en: string;

  @IsString()
  @IsNotEmpty()
  @MinLength(4)
  @MaxLength(40)
  ar: string;
}

export class VideoDTO {
  @IsDefined()
  @IsNotEmptyObject()
  @IsObject()
  @ValidateNested()
  @Type(() => MultiLanguageDTO)
  name!: MultiLanguageDTO;
}
person tarek noaman    schedule 19.07.2020