Разобрался, в общем. Нужно просто сделать свой 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. подсмотрел
вот тут.