Swagger
基于最新的 OpenAPI 3.0.3 实现了新版的 Swagger 组件。
相关信息:
描述 | |
---|---|
可用于标准项目 | ✅ |
可用于 Serverless | ❌ |
可用于一体化 | ❌ |
包含独立主框架 | ❌ |
包含独立日志 | ❌ |
安装依赖
$ npm install @midwayjs/swagger@3 --save
$ npm install swagger-ui-dist --save-dev
如果想要在服务器上输出 Swagger API 页面,则需要将 swagger-ui-dist
安装到依赖中。
$ npm install swagger-ui-dist --save
或者在 package.json
中增加如下依赖后,重新安装。
{
"dependencies": {
"@midwayjs/swagger": "^3.0.0",
// 如果你希望在服务器上使用
"swagger-ui-dist": "^4.2.1",
// ...
},
"devDependencies": {
// 如果你不希望在服务器上使用
"swagger-ui-dist": "^4.2.1",
// ...
}
}
开启组件
在 configuration.ts
中增加组件。
import { Configuration } from '@midwayjs/core';
import * as swagger from '@midwayjs/swagger';
@Configuration({
imports: [
// ...
swagger
]
})
export class MainConfiguration {
}
可以配置启用的环境,比如下面的代码指的是 只在 local 环境下启用。
import { Configuration } from '@midwayjs/core';
import * as swagger from '@midwayjs/swagger';
@Configuration({
imports: [
// ...
{
component: swagger,
enabledEnvironment: ['local']
}
]
})
export class MainConfiguration {
}
然后启动项目,访问地址:
路径可以通过 swaggerPath
参数配置。
数据类型
自动类型提取
Swagger 组件会识别各个 @Controller
中每个路由方法的 @Body()
、@Query()
、@Param()
装饰器,提取路由方法参数和类型。
比如下面的代码:
@Get('/')
async home(
@Query('uid') uid: number,
@Query('tid') tid: string,
@Query('isBoolean') isBoolean: boolean,
) {
// ...
}
基础的布尔,字符串,数字类型展示效果如下:
类型和 Schema
我们常在参数使用对象,并使用定义好的类作为类型,这个时候 swagger 组件也能自动识别,同时也能和普通的类型进行组合识别。
比如下面的代码:
@Post('/:id', { summary: 'test'})
async create(@Body() createCatDto: CreateCatDto, @Param('id') id: number) {
// ...
}
CreateCatDto
类型的定义如下,我们使用 ApiProperty
将其中的每个属性都进行了定义。
import { ApiProperty } from "@midwayjs/swagger";
export class CreateCatDto {
@ApiProperty({ example: 'Kitty', description: 'The name of the Catname'})
name: string;
@ApiProperty({ example: '1', description: 'The name of the Catage'})
age: number;
@ApiProperty({ example: 'bbbb', description: 'The name of the Catbreed'})
breed: string;
}
效果如下,组件会自动提取其中的两个参数:
同时,由于在类中定义了每个属性的 example,会自动填入示例值。
在 Swagger 中,每个类型都会有一个 Schema
来描述,我们已经定义了一个 CreateCatDto
的 Schema,看起来就像是下面的样子。
注意,我们会重复用到这些 Schema。
基础类型
通过给 @ApiProperty(...)
装饰器中设置 type,我们可以定义常见的类型。
大多数情况下,基础类型无需显式声明 type
,可自动识别。
字符串
@ApiProperty({
type: 'string',
// ...
})
name: string;
布尔类型
@ApiProperty({
type: 'boolean',
example: 'true',
// ...
})
isPure: boolean;
数字类型
@ApiProperty({
type: 'number',
example: '1',
description: 'The name of the Catage'
})
age: number;
此外,也可以使用 format 字段来定义更为精确的长度。
@ApiProperty({
type: 'integer',
format: 'int32',
example: '1',
description: 'The name of the Catage'
})
age: number;
数组类型
如果是数组类型,我们可以配置 type 字段来定义,同时通过 items
的 type
来指定类型。
@ApiProperty({
type: 'array',
items: {
type: 'string',
},
example: ['1'],
description: 'The name of the Catage'
})
breeds: string[];
枚举类型
如果是枚举类型,可以通过配置 enmu 字段来定义。
enum HelloWorld {
One = 'One',
Two = 'Two',
Three = 'Three',
}
@ApiProperty({
enum: ['One', 'Two', 'Three'],
description: 'The name of the Catage'
})
hello: HelloWorld;
如果该字段在最顶层,展示效果如下:
复杂对象类型
如果某个属性的类型是个现有的复杂类型, 我们可以使用 type
来指定这个复杂的类型。
export class Cat {
/**
* The name of the Catcomment
* @example Kitty
*/
@ApiProperty({ example: 'Kitty', description: 'The name of the Cat'})
name: string;
@ApiProperty({ example: 1, description: 'The age of the Cat' })
age: number;
@ApiProperty({ example: '2022-12-12 11:11:11', description: 'The age of the CatDSate' })
agedata?: Date;
@ApiProperty({
example: 'Maine Coon',
description: 'The breed of the Cat',
})
breed: string;
}
export class CreateCatDto {
// ...
@ApiProperty({
type: Cat, // 这里无需指定 example
})
related: Cat;
}
效果如下:
复杂对象数组类型
如果某个属性的类型是个复杂的数组类型,写法略有不同。
首先type
必须声明为 array
,除了设置type
,我们还可以使用 getSchemaPath
方法额外导入一个不同的类型(上面的复杂对象也可以使用它设置$ref)。
此外,如果 Cat
类型没有在其他属性的 type
字段中声明过,需要使用 @ApiExtraModel
装饰器额外声明引入外部类型。
import { ApiProperty, getSchemaPath, ApiExtraModel } from '@midwayjs/swagger';
class Cat {
// ...
}
@ApiExtraModel(Cat)
export class CreateCatDto {
// ...
@ApiProperty({
type: 'array',
items: {
$ref: getSchemaPath(Cat),
}
})
relatedList: Cat[];
}
效果如下:
循环依赖
当类之间具有循环依赖关系时,请使用惰性函数提供类型信息。
比如 type
字段的循环。
class Photo {
// ...
@ApiProperty({
type: () => Album
})
album: Album;
}
class Album {
// ...
@ApiProperty({
type: () => Photo
})
photo: Photo;
}