@lookingfor2

Как изменить ответ валидатора class-validator при валидации запроса?

Суть в том что на данный момент валидатор возвращает ответ такого вида
{
    "statusCode": 422,
    "message": [
        "Поле «ФИО» обязательно для заполнения",
        "Поле «Email» должно быть валидным email",
        "Поле «Email» обязательно для заполнения",
        "Поле «Пароль» должно быть не меньше 8 и не больше 24 символов",
        "Поле «Пароль» обязательно для заполнения",
        "Поле «Подтвердите пароль» обязательно для заполнения"
    ],
    "error": "Unprocessable Entity"
}


хотелось бы чтобы возвращались ошибки в таком формате
{
    "statusCode": 422,
    "message": [
        "fio":["Поле «ФИО» обязательно для заполнения"],
        "email": [
            "Поле «Email» должно быть валидным email",
            "Поле «Email» обязательно для заполнения"
        ],
        "password": [
            "Поле «Пароль» должно быть не меньше 8 и не больше 24 символов",
            "Поле «Пароль» обязательно для заполнения",
        ],

    ],
    "error": "Unprocessable Entity"
}


мой dto файл
import { ApiProperty } from '@nestjs/swagger';
import { IsEmail, IsNotEmpty, Length, validate } from 'class-validator';
import { Match } from '../../decorators/match.decorator';

export class UserRegisterRequestDto {
  @ApiProperty({
    description: 'Имя пользователя',
    example: 'Петр Ян',
  })
  @IsNotEmpty({ message: 'Поле «ФИО» обязательно для заполнения'})
  name: string;

  @ApiProperty({
    description: 'Email пользователя',
    example: 'petr.yn@gmail.com',
  })
  @IsNotEmpty({
    message: 'Поле «Email» обязательно для заполнения',
    groups: ['test'],
  })
  @IsEmail(
    {},
    { message: 'Поле «Email» должно быть валидным email', groups: ['test'] },
  )
  email: string;

  @ApiProperty({
    description: 'Пароль пользователя',
    example: 'tipira21',
  })
  @IsNotEmpty({ message: 'Поле «Пароль» обязательно для заполнения' })
  @Length(8, 24, {
    message: 'Поле «Пароль» должно быть не меньше 8 и не больше 24 символов',
  })
  password: string;

  @ApiProperty({
    description: 'Подтвердить пароль',
    example: 'tipira21',
  })
  @Match<UserRegisterRequestDto>('password', {
    message: 'Поле «Подтвердите пароль» должно совпадать с полем «Пароль»',
  })
  @IsNotEmpty({ message: 'Поле «Подтвердите пароль» обязательно для заполнения' })
  confirm: string;
}
// validate(UserRegisterRequestDto).then((errors) => console.log(errors));
  • Вопрос задан
  • 512 просмотров
Решения вопроса 2
@lookingfor2 Автор вопроса
// main.ts точка входа
async function bootstrap() {
  const app = await NestFactory.create(AppModule, { cors: true });

  // We'll start by binding ValidationPipe at the application level,
  // thus ensuring all endpoints are protected from receiving incorrect data.
  app.useGlobalPipes(
    new ValidationPipe({
      exceptionFactory: (errors: ValidationError[]) => {
        return new BadRequestException(formatErrorsHelper(errors));
      },
    }),
  );
  // swagger
  const config = new DocumentBuilder()
    .setTitle('Salary365 manager API')
    .setDescription('Salary365 manager API description')
    .setVersion('1.0')
    .addBearerAuth(
      { type: 'http', scheme: 'bearer', bearerFormat: 'JWT' },
      'access-token',
    )
    .build();
  const document = SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('/api', app, document);
  // start listen and serve port from env
  await app.listen(process.env.APP_PORT);
}

// хелпер для мутации ответа
import { ValidationError } from '@nestjs/common/interfaces/external/validation-error.interface';

export const formatErrorsHelper = (errors: ValidationError[]) =>
  errors.map((item) => ({ [item.property]: Object.values(item.constraints) }));
Ответ написан
Комментировать
yarkov
@yarkov Куратор тега JavaScript
Помог ответ? Отметь решением.
lookingfor2 В вашем варианте будет работать только на плоской структуре DTO:
{
    "message": ""// Ошибка валидации тут
}


Вот такая реализация учитывает вложенные поля, при валидации которых возникнет ошибка:
{
    "message": "",
    "parent": {
        "child": "" // Ошибка валидации тут
    }
}


type IErrorMessage = Record<string, any>;

function formatErrorsHelper(errors: ValidationError[]): IErrorMessage[] {
  return errors.map((item): IErrorMessage => {
    const { property, constraints, children } = item;
    const result: IErrorMessage = {};

    if (constraints) {
      result[property] = Object.values(constraints);
    }

    if (Array.isArray(children) && children.length > 0) {
      result[property] = formatErrorsHelper(children);
    }

    return result;
  });
}

Функция вернёт такой массив:
{
    "message": ["Сообщение об ошибке валидации"],
    "parent": [
        {
            "child": ["Сообщение об ошибке валидации"]
        }
    ]
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы