@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")
}
  • Вопрос задан
  • 549 просмотров
Решения вопроса 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. подсмотрел вот тут.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

Похожие вопросы
22 нояб. 2024, в 22:26
3500 руб./за проект
22 нояб. 2024, в 21:47
3000 руб./за проект
22 нояб. 2024, в 21:44
50000 руб./за проект