Types et paramètres
Le SwaggerModule
recherche tous les decorateurs @Body()
, @Query()
et @Param()
dans les gestionnaires de routes pour générer le document API. Il crée également des définitions de modèles correspondantes en tirant parti de la réflexion. Considérez le code suivant :
@Post()async create(@Body() createCatDto: CreateCatDto) { this.catsService.create(createCatDto);}
Basé sur le CreateCatDto
, la définition de modèle suivante sera créée pour Swagger UI :
Comme vous pouvez le voir, la définition est vide bien que la classe ait quelques propriétés déclarées. Pour rendre les propriétés de la classe visibles pour le SwaggerModule
, nous devons soit les annoter avec le décorateur @ApiProperty()
, soit utiliser le plugin CLI (en savoir plus dans la section Plugin) qui le fera automatiquement :
import { ApiProperty } from '@nestjs/swagger';
export class CreateCatDto { @ApiProperty() name: string;
@ApiProperty() age: number;
@ApiProperty() breed: string;}
Ouvrons le navigateur et vérifions le modèle CreateCatDto
généré :
De plus, le décorateur @ApiProperty()
permet de définir diverses propriétés de l’objet de schéma :
@ApiProperty({ description: 'L\'âge d\'un chat', minimum: 1, default: 1,})age: number;
Pour définir explicitement le type de la propriété, utilisez la clé type
:
@ApiProperty({ type: Number,})age: number;
Tableaux
Lorsque la propriété est un tableau, nous devons indiquer manuellement le type du tableau comme indiqué ci-dessous :
@ApiProperty({ type: [String] })names: string[];
Vous pouvez inclure soit le type comme le premier élément d’un tableau (comme indiqué ci-dessus), soit définir la propriété isArray
sur true
.
Dépendances circulaires
Lorsqu’il y a des dépendances circulaires entre les classes, utilisez une fonction paresseuse pour fournir au SwaggerModule
des informations de type :
@ApiProperty({ type: () => Node })node: Node;
Généralités et interfaces
Comme TypeScript ne stocke pas les métadonnées sur les génériques ou les interfaces, lorsque vous les utilisez dans vos DTO, le SwaggerModule
peut ne pas être en mesure de générer correctement les définitions de modèle au moment de l’exécution. Par exemple, le code suivant ne sera pas correctement inspecté par le module Swagger :
createBulk(@Body() usersDto: CreateUserDto[]) {}
Pour surmonter cette limitation, vous pouvez définir le type explicitement :
@ApiBody({ type: [CreateUserDto] })createBulk(@Body() usersDto: CreateUserDto[]) {}
Enums
Pour identifier un enum
, nous devons définir manuellement la propriété enum
sur le @ApiProperty
avec un tableau de valeurs :
@ApiProperty({ enum: ['Admin', 'Moderator', 'User'] })role: UserRole;
Alternativement, définissez un véritable enum TypeScript comme suit :
export enum UserRole { Admin = 'Admin', Moderator = 'Moderator', User = 'User',}
Vous pouvez ensuite utiliser l’enum directement avec le décorateur de paramètre @Query()
en combinaison avec le décorateur @ApiQuery()
:
@ApiQuery({ name: 'role', enum: UserRole })async filterByRole(@Query('role') role: UserRole = UserRole.User) {}
Avec isArray
défini sur true, l’enum
peut être sélectionné comme un multi-sélect :
Schéma d’énumérations
Par défaut, la propriété enum
ajoutera une définition brute d’Enum sur le parameter
.
- breed: type: 'string' enum: - Persian - Tabby - Siamese
La spécification ci-dessus fonctionne bien dans la plupart des cas. Cependant, si vous utilisez un outil qui prend la spécification comme entrée et génère du code côté client, vous pouvez rencontrer un problème avec le code généré contenant des enums
dupliqués. Considérez le code suivant :
export class CatDetail { breed: CatDetailEnum;}
export class CatInformation { breed: CatInformationEnum;}
export enum CatDetailEnum { Persian = 'Persian', Tabby = 'Tabby', Siamese = 'Siamese',}
export enum CatInformationEnum { Persian = 'Persian', Tabby = 'Tabby', Siamese = 'Siamese',}
Vous pouvez voir que vous avez maintenant deux enums
qui sont exactement les mêmes. Pour résoudre ce problème, vous pouvez passer un enumName
avec la propriété enum
dans votre décorateur.
export class CatDetail { @ApiProperty({ enum: CatBreed, enumName: 'CatBreed' }) breed: CatBreed;}
La propriété enumName
permet à @nestjs/swagger
de transformer CatBreed
en son propre schéma
, ce qui rend l’enum CatBreed
réutilisable. La spécification ressemblera à ceci :
CatDetail: type: 'object' properties: ... - breed: schema: $ref: '#/components/schemas/CatBreed'CatBreed: type: string enum: - Persian - Tabby - Siamese
Définitions brutes
Dans certains scénarios spécifiques (par exemple, des tableaux profondément imbriqués, des matrices), vous pouvez vouloir décrire votre type manuellement.
@ApiProperty({ type: 'array', items: { type: 'array', items: { type: 'number', }, },})coords: number[][];
De même, pour définir votre contenu d’entrée/sortie manuellement dans les classes de contrôleur, utilisez la propriété schema
:
@ApiBody({ schema: { type: 'array', items: { type: 'array', items: { type: 'number', }, }, },})async create(@Body() coords: number[][]) {}
Modèles supplémentaires
Pour définir des modèles supplémentaires qui ne sont pas directement référencés dans vos contrôleurs mais qui doivent être inspectés par le module Swagger, utilisez le décorateur @ApiExtraModels()
:
@ApiExtraModels(ExtraModel)export class CreateCatDto {}
Alternativement, vous pouvez passer un objet d’options avec la propriété extraModels
spécifiée au méthode SwaggerModule#createDocument()
, comme suit :
const document = SwaggerModule.createDocument(app, options, { extraModels: [ExtraModel],});
Pour obtenir une référence ($ref
) à votre modèle, utilisez la fonction getSchemaPath(ExtraModel)
:
'application/vnd.api+json': schema: $ref: getSchemaPath(ExtraModel)
oneOf, anyOf, allOf
Pour combiner des schémas, vous pouvez utiliser les mots-clés oneOf
, anyOf
ou allOf
(en savoir plus).
@ApiProperty({ oneOf: [ { $ref: getSchemaPath(Cat) }, { $ref: getSchemaPath(Dog) }, ],})pet: Cat | Dog;
Si vous souhaitez définir un tableau polymorphe (c’est-à-dire un tableau dont les membres s’étendent sur plusieurs schémas), vous devez utiliser une définition brute (voir ci-dessus) pour définir votre type manuellement.
type Pet = Cat | Dog;
@ApiProperty({ type: 'array', items: { oneOf: [ { $ref: getSchemaPath(Cat) }, { $ref: getSchemaPath(Dog) }, ], },})pets: Pet[];
Les deux Cat
et Dog
doivent être définis comme modèles supplémentaires en utilisant le décorateur @ApiExtraModels()
(au niveau de la classe).