D
D
Dmitry Sviridov2020-04-24 00:14:23
JavaScript
Dmitry Sviridov, 2020-04-24 00:14:23

How to generate validation error output in NestJS?

I'm trying to do a validation following the example from the NestJS framework documentation . The problem is that the API response is given in case of an error in the form "{"statusCode": 400,"message": ["id must be a number string"],"error": "Bad Request"}".
I'd like to remake this to be the following:

  1. So that errors are displayed not just as lines, but as a key-value object (so that at the front one can understand in which field the error occurred). At the same time, so that the field name does not appear in the error text itself
  2. To be able to translate errors into other languages

If we talk about the first point, then, as I understand it, this is implemented by creating a descendant of the ValidationPipe class, but at the same time I do not understand how to get the name of the field in which the error occurred, and how to get the error text without specifying the field in it. How to do it right?

Here is a code snippet.
// DTO
export class CreatePostDto {
  @IsNumberString()
  id: number;
}
...
// Controller
@Post()
async create(@Body() createPostDto: CreatePostDto) {
  console.dir("CREATED")
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Dmitry Sviridov, 2020-04-24
@dimuska139

Understood, in general. You just need to make your 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);
  }
}

And use it in the controller like this:
@UsePipes(new ValidationPipe())
@Post()
async create(@Body() createPostDto: CreatePostDto) {
  console.dir(createPostDto)
}

In the line result[prop] = constraint[0]; 0 for a reason. constraint[0] contains the "key" of the error. For example, "isNotEmpty". That is, using this key, you can make your own text of the error, including the translation. prop is the name of the field where the error occurred. And constraint[1] contains the standard text of the validator, which contains the name of the field (I don't need it).
Ps peeped here .

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question