[ ] Regression
[ ] Bug report
[X] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.
You have to duplicate annotations with both class validator AND swagger to get input validation and swagger support. Seems like we should be able to validate input based on the swagger annotations - they compile to JSON Schema.
I'm guessing this isn't already possible as it would be in the recipe
Nest version: 5.4.1
There's a very old conversation about this over at https://github.com/typestack/class-validator/issues/5
Ideally, it'd be nice if the solution that we came up for this was _not_ Nest-specific (and could be used anywhere that class-validator is used).
Jumping in.
I discovered https://github.com/epiphone/class-validator-jsonschema which may fill the gap ? We are using class-validator quite extensively.
I see that you are thinking about the other way around, not sure which way is the best.
Ok, I have a quick and dirty solution for now.
Keep in mind that my goal is to minimize code duplication, and as class-validator is basically documenting the same way swagger annotations would, and that I need class-validator, I focused on this solution. But it may not fit your needs.
So, for now you can use https://github.com/epiphone/class-validator-jsonschema, and this won't require any change on @nest/swagger side :
Main.ts :
import { NestFactory } from '@nestjs/core';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { AppModule } from './modules/app.module';
import dotenv = require('dotenv-extended');
import * as cors from 'cors';
import { getFromContainer, MetadataStorage } from 'class-validator';
import { validationMetadatasToSchemas } from 'class-validator-jsonschema';
import config from './config';
async function bootstrap() {
dotenv.load();
const app = await NestFactory.create(AppModule);
app.use(cors(config.cors));
// swagger
const swaggerConfig = new DocumentBuilder().setTitle('Vaneau neuf swagger').build();
const document = SwaggerModule.createDocument(app, swaggerConfig);
// Creating all the swagger schemas based on the class-validator decorators
const metadatas = (getFromContainer(MetadataStorage) as any).validationMetadatas;
const schemas = validationMetadatasToSchemas(metadatas);
document.definitions = schemas;
SwaggerModule.setup(config.swagger.route, app, document);
await app.listen(3001);
}
bootstrap();
Dtos :
import { Min, Max, IsUUID, IsArray, ValidateNested, IsString } from 'class-validator';
export class TestDTO {
@IsUUID()
public id: string;
@IsArray()
@IsString({ each: true })
public wishes: string[];
@Min(10)
public surface: number;
}
// tslint:disable-next-line:max-classes-per-file
export class OtherTestDTO {
@IsString()
public firstname: string;
@IsString()
public lastname: string;
@Min(0)
@Max(99)
public age: number;
@ValidateNested()
public test: TestDTO;
}
Example controller :
import { Controller, Get, HttpStatus, Post, Body } from '@nestjs/common';
import { ApiResponse, ApiOkResponse, ApiUnauthorizedResponse } from '@nestjs/swagger';
import { TestDTO, OtherTestDTO } from './testDTO';
@Controller()
export class AppController {
@Get('/hello')
@ApiOkResponse({ description: 'A test route', type: OtherTestDTO })
@ApiUnauthorizedResponse({ description: 'An error' })
getHelloWorld(): OtherTestDTO {
return {
age: 98,
firstname: 'jos茅',
lastname: 'pr茅vot',
test: { id: 'lol', surface: 4695, wishes: [] },
};
}
@Post()
@ApiOkResponse({ description: 'The newly created item', type: TestDTO })
@ApiUnauthorizedResponse({ description: 'An error' })
postHello(@Body() createCatDto: OtherTestDTO): TestDTO {
return { id: 'lol', surface: 4695, wishes: [] };
}
}
Result :

This will be solved by #191. Let's track this there
Ok, I have a quick and dirty solution for now.
I have changed your code a bit. @nestjs/swagger has changed a bit and this is the most recent working code for me:
import {getFromContainer, MetadataStorage} from 'class-validator';
import {validationMetadatasToSchemas} from 'class-validator-jsonschema';
....
const metadata = (getFromContainer(MetadataStorage) as any).validationMetadatas;
document.components.schemas = Object.assign({}, document.components.schemas || {}, validationMetadatasToSchemas(metadata));
Make sure to install the following
npm install class-validator class-transformer class-validator-jsonschema
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
Ok, I have a quick and dirty solution for now.
Keep in mind that my goal is to minimize code duplication, and as class-validator is basically documenting the same way swagger annotations would, and that I need class-validator, I focused on this solution. But it may not fit your needs.
So, for now you can use https://github.com/epiphone/class-validator-jsonschema, and this won't require any change on @nest/swagger side :
Main.ts :
Dtos :
Example controller :
Result :