validating an array of uuids in nestjs swagger body

Viewed 1117

It sounds like a quite simple question but I've been searching for a solution for a very long time now. I want to validate an array of UUIDs in an endpoint.

Like this: ["9322c384-fd8e-4a13-80cd-1cbd1ef95ba8", "986dcaf4-c1ea-4218-b6b4-e4fd95a3c28e"]

I have already successfully implemented it as a JSON object { "id": ["9322c384-fd8e-4a13-80cd-1cbd1ef95ba8", "986dcaf4-c1ea-4218-b6b4-e4fd95a3c28e"]} with the following code:

public getIds(
  @Body(ValidationPipe)
  uuids: uuidDto
) {
  console.log(uuids);
}
import { ApiProperty } from '@nestjs/swagger';
import { IsUUID } from 'class-validator';

export class uuidDto {
  @IsUUID('4', { each: true })
  @ApiProperty({
    type: [String],
    example: [
      '9322c384-fd8e-4a13-80cd-1cbd1ef95ba8',
      '986dcaf4-c1ea-4218-b6b4-e4fd95a3c28e',
    ],
  })
  id!: string;
}

But unfortunately I can't customize the function that calls that endpoint. So I need a solution to only validate a array of uuids.

2 Answers

instead of type string , write string[]. like below:

import { ApiProperty } from '@nestjs/swagger';
import { IsUUID } from 'class-validator';

export class uuidDto {
  @IsUUID('4', { each: true })
  @ApiProperty({
    type: string[],
    example: [
      '9322c384-fd8e-4a13-80cd-1cbd1ef95ba8',
      '986dcaf4-c1ea-4218-b6b4-e4fd95a3c28e',
    ],
  })
  id!: string[];
}

You can build a custom validation pipe for it:

@Injectable()
export class CustomClassValidatorArrayPipe implements PipeTransform {

  constructor(private classValidatorFunction: (any)) {}

  transform(value: any[], metadata: ArgumentMetadata) {
    const errors = value.reduce((result, value, index) => {
      if (!this.classValidatorFunction(value))
        result.push(`${value} at index ${index} failed validation`)
      return result
    }, [])

    if (errors.length > 0) {
      throw new BadRequestException({
        status: HttpStatus.BAD_REQUEST,
        message: 'Validation failed',
        errors
      });
    }

    return value;
  }
}

In your controller:

@Post()
createExample(@Body(new CustomClassValidatorArrayPipe(isUUID)) body: string[]) {
  ...
}
  • Ensure to use the lowercase functions from class-validator. It has to be isUUID instead of IsUUID. (This is used for the manual validation with class-validator.)
  • CustomClassValidatorArrayPipe is build modular. You can validate any other type with it. For example a MongoId: @Body(new CustomClassValidatorArrayPipe(isMongoId)) body: ObjectId[]

Result

If you send this:

POST http://localhost:3000/example
Content-Type: application/json

[
  "986dcaf4-c1ea-4218-b6b4-e4fd95a3c28e",
  "123",
  "test"
]

Server will reply:

{
  "status": 400,
  "message": "Validation failed",
  "errors": [
    "123 at index 1 failed validation",
    "test at index 2 failed validation"
  ]
}
Related