@dimuska139
Backend developer

Как в NestJS сформировать вывод ошибок валидации?

Пытаюсь сделать валидацию по примеру из документации фреймворка NestJS. Проблема в том, что ответ API отдается в случае ошибки в виде "{"statusCode": 400,"message": ["id must be a number string"],"error": "Bad Request"}".
Мне бы хотелось переделать это, чтобы было следующее:
  1. Чтобы ошибки выводились не просто строками, а в виде объекта "ключ-значение" (чтобы на фронте можно было понять, в каком именно поле ошибка возникла). При этом чтобы в самом тексте ошибки название поля не фигурировало
  2. Чтобы была возможность перевести ошибки на другие языки

Если говорить о первом моменте, то, я так понимаю, это реализуется путем создания потомка класса ValidationPipe, но при этом я не понимаю, как получить название поля, в котором ошибка возникла, и как получить текст ошибки без указания поля в нем. Как это сделать правильно?

Вот фрагмент кода.
// DTO
export class CreatePostDto {
  @IsNumberString()
  id: number;
}
...
// Controller
@Post()
async create(@Body() createPostDto: CreatePostDto) {
  console.dir("CREATED")
}
  • Вопрос задан
  • 469 просмотров
Решения вопроса 1
@dimuska139 Автор вопроса
Backend developer
Разобрался, в общем. Нужно просто сделать свой ValidationPipe:
@Injectable()
export class ValidationPipe implements PipeTransform<any> {
  async transform(value, metadata: ArgumentMetadata) {

    if (!value) {
      throw new BadRequestException('No data submitted');
    }

    const { metatype } = metadata;
    if (!metatype || !this.toValidate(metatype)) {
      return value;
    }
    const object = plainToClass(metatype, value);
    console.dir(object);
    const errors = await validate(object);
    if (errors.length > 0) {
      throw new HttpException({message: 'Input data validation failed', errors:  this.buildError(errors)}, HttpStatus.BAD_REQUEST);
    }
    return value;
  }

  private buildError(errors) {
    const result = {};
    errors.forEach(el => {
      const prop = el.property;
      Object.entries(el.constraints).forEach(constraint => {
        result[prop] = constraint[0];
      });
    });
    return result;
  }

  private toValidate(metatype): boolean {
    const types = [String, Boolean, Number, Array, Object];
    return !types.find((type) => metatype === type);
  }
}


И использовать его в контроллере вот так:
@UsePipes(new ValidationPipe())
@Post()
async create(@Body() createPostDto: CreatePostDto) {
  console.dir(createPostDto)
}


В строке result[prop] = constraint[0]; 0 не просто так. В constraint[0] находится "ключ" ошибки. Например, "isNotEmpty". То есть по этому ключу можно сделать свой текст ошибки, в том числе и перевод. prop - это название поля, в котором возникла ошибка. А в constraint[1] находится стандартный текст валидатора, в котором фигурирует название поля (мне он не нужен).

P.s. подсмотрел вот тут.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы
summer Ярославль
от 100 000 до 140 000 ₽
КРАФТТЕК Санкт-Петербург
от 60 000 до 80 000 ₽
19 апр. 2024, в 20:43
20000 руб./за проект
19 апр. 2024, в 20:11
500 руб./за проект