💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
## 类型和参数 `SwaggerModule`在路径处理程序上搜索所有`@Body()`, `@Query()`, 以及`@Param()`装饰器来生成API文档。它也利用反射来创建响应模型。考虑以下代码: ```TypeScript @Post() async create(@Body() createCatDto: CreateCatDto) { this.catsService.create(createCatDto); } ``` > 要显式定义主体,使用`@ApiBody()`装饰器 (从`@nestjs/swagger`引入). 基于`CreateCatDto`,将创建以下Swagger页面模型。 ![](https://docs.nestjs.com/assets/swagger-dto.png) 如你所见,虽然类已经声明了一些属性,但这里的定义是空的。要使这些类属性在`SwaggerModule`中可见,我们要么用`@ApiProperty()`装饰器或使用`CLI`插件来自动生成: ```TypeScript import { ApiProperty } from '@nestjs/swagger'; export class CreateCatDto { @ApiProperty() name: string; @ApiProperty() age: number; @ApiProperty() breed: string; } ``` > 考虑使用Swagger插件(参见[CLI插件](#CLI插件))来自动生成以代替手动装饰每个属性。 打开浏览器确认生成的`CreateCatDto`模型: ![](https://docs.nestjs.com/assets/swagger-dto2.png) `@ApiProperty()`装饰器也允许设置不同的原型对象属性: ```TypeScript @ApiProperty({ description: 'The age of a cat', minimum: 1, default: 1, }) age: number; ``` > 可以使用`@ApiPropertyOptional()`速记装饰器来替代显式输入`@ApiProperty({ required: false })`。 要显式指定属性类型,使用`type`字段: ```TypeScript @ApiProperty({ type: Number, }) age: number; ``` ### 数组 当属性是数组时,我们必须手动指定数组类型: ```TypeScript @ApiProperty({ type: [String] }) names: string[]; ``` > 考虑使用Swagger 插件来自动发现数组 要么将类型作为数组的第一个元素(如上),要么将`isArray`属性设为`true`。 ### 循环依赖 当你的类之间有循环依赖时,使用`SwaggerModul`提供的一个包含类型信息的懒函数。 ```TypeScript @ApiProperty({ type: () => Node }) node: Node; ``` > 考虑使用Swagger 插件来自动发现循环依赖 ### 泛型和接口 由于`TypeScript`没有存储泛型或者接口的元数据,当你在DTO中使用他们的时候,`SwaggerModule`可能不会正确生成运行时的模型定义。基于此,下列代码不会被Swagger模块正确识别。 ```TypeScript createBulk(@Body() usersDto: CreateUserDto[]) ``` 要处理这些限制,需要显式配置类型: ```TypeScript @ApiBody({ type: [CreateUserDto] }) createBulk(@Body() usersDto: CreateUserDto[]) ``` ### 枚举 要定义一个枚举,需要在`@ApiProperty`中用数组手动设置`enum`属性。 ```TypeScript @ApiProperty({ enum: ['Admin', 'Moderator', 'User']}) role: UserRole; ``` 也可以如下定义一个真实的`TypeScript`泛型: ```TypeScript export enum UserRole { Admin = 'Admin', Moderator = 'Moderator', User = 'User', } ``` 可以在`@Query()`参数中配合`@ApiQuery()`装饰器直接使用`enum`: ```TypeScript @ApiQuery({ name: 'role', enum: UserRole }) async filterByRole(@Query('role') role: UserRole = UserRole.User) {} ``` ![](https://docs.nestjs.com/assets/enum_query.gif) 当`isArray`配置为`true`时, `enum`可以多选。 ![](https://docs.nestjs.com/assets/enum_query_array.gif) ### 枚举原型 默认地,`enum`属性将为[Enum](https://swagger.io/docs/specification/data-models/enums/)在`parameter`上添加一个原始定义。 ```TypeScript - breed: type: 'string' enum: - Persian - Tabby - Siamese ``` 上述定义在大部分情况下工作良好。然而,如果你使用该定义作为输入在客户端生成代码时,可能会遇到属性包含重复枚举的情况,考虑以下代码: ```TypeScript // generated client-side code 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', } ``` > 上述代码使用[NSwag](https://github.com/RicoSuter/NSwag)工具生成 现在可以看到有两个枚举完全一样,要处理这个问题,需要在装饰器的`enum`属性中传入`enumName`参数。 ```TypeScript export class CatDetail { @ApiProperty({ enum: CatBreed, enumName: 'CatBreed' }) breed: CatBreed; } ``` `enumName`属性使能`@nestjs/swagger`来将`CatBreed`转换为其原型,从而使`CatBreed`可重用: ```TypeScript CatDetail: type: 'object' properties: ... - breed: schema: $ref: '#/components/schemas/CatBreed' CatBreed: type: string enum: - Persian - Tabby - Siamese ``` > 任何包含`enum`属性的装饰器都有`enumName` ### 原始定义 在一些特殊场合(例如深度嵌套的数组和矩阵),你可能需要手动描述你的类型。 ```TypeScript @ApiProperty({ type: 'array', items: { type: 'array', items: { type: 'number', }, }, }) coords: number[][]; ``` 类似地,要在控制器类中手动定义输入输出,使用`schema`属性: ```TypeScript @ApiBody({ schema: { type: 'array', items: { type: 'array', items: { type: 'number', }, }, }, }) async create(@Body() coords: number[][]) {} ``` ### 额外模型 要定义控制器中没有直接使用,但是需要被Swagger模块检查的额外的模型,使用`@ApiExtraModels()`装饰器: ```TypeScript @ApiExtraModels(ExtraModel) export class CreateCatDto {} ``` > 只需要对指定的model类使用一次`@ApiExtraModels()` 你也可以把一个选项对象和`extraModels`属性一起传递给`SwaggerModule#createDocument()` 方法: ```TypeScript const document = SwaggerModule.createDocument(app, options, { extraModels: [ExtraModel], }); ``` 要获得一个模型的引用(`$ref`) ,使用`getSchemaPath(ExtraModel)`函数: ```TypeScript 'application/vnd.api+json': { schema: { $ref: getSchemaPath(ExtraModel) }, }, ``` ### `oneOf`, `anyOf`, `allOf` 要组合原型,你可以使用`oneOf`,`anyOf` 或者`allOf`关键词([阅读更多](https://swagger.io/docs/specification/data-models/oneof-anyof-allof-not/)). ```TypeScript @ApiProperty({ oneOf: [ { $ref: getSchemaPath(Cat) }, { $ref: getSchemaPath(Dog) }, ], }) pet: Cat | Dog; ``` 如果你要定义一个多态数组(例如,数组成员跨越多个原型),你应该使用前节的原始定义来手动定义你的类型。 ```TypeScript type Pet = Cat | Dog; @ApiProperty({ type: 'array', items: { oneOf: [ { $ref: getSchemaPath(Cat) }, { $ref: getSchemaPath(Dog) }, ], }, }) pets: Pet[]; ``` > `getSchemaPath()`函数从`@nestjs/swagger`引入. `Cat`和`Dog`都应该使用`@ApiExtraModels()`装饰器 (在类水平).