首页 / NestJS 入门教程 / Swagger 与 OpenAPI

NestJS 入门教程

Swagger 与 OpenAPI

本教程共 47 篇 · 第 41 篇 · 更新于 2026-08-09 · 约 12 分钟阅读

NestJSSwaggerOpenAPIAPI文档ApiPropertyApiOperation

本节目标:学会在 NestJS 中集成 Swagger,用装饰器自动生成完整的 API 文档,让前端同事不再追着你要接口文档。

为什么需要 API 文档

你写的 API 有 50 个接口,每个接口的参数、返回值都不一样。没有文档的话,前端同事只能靠猜或者靠问你。

OpenAPI(以前叫 Swagger)是一套描述 RESTful API 的标准格式。你用一套标准格式把接口描述清楚,然后就能自动生成漂亮的交互式文档页面。前端同事打开网页就能看到所有接口,还能直接在线调试。

NestJS 跟 Swagger 的集成非常丝滑。因为 NestJS 本身就有丰富的装饰器和类型信息,大部分文档可以自动生成,你只需要补一些细节就行。

安装

npm i --save @nestjs/swagger

就这一个包,搞定一切。

快速上手

main.ts 里加几行代码就能跑起来:

import { NestFactory } from '@nestjs/core';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  const config = new DocumentBuilder()
    .setTitle('猫咪 API')
    .setDescription('一个管理猫咪的接口服务')
    .setVersion('1.0')
    .addTag('cats')
    .build();

  const documentFactory = () => SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('api', app, documentFactory);

  await app.listen(3000);
}
bootstrap();

启动服务后,打开 http://localhost:3000/api 就能看到 Swagger UI 页面了。

这段代码做了三件事:

  1. DocumentBuilder 构建文档的基本信息(标题、描述、版本)
  2. SwaggerModule.createDocument() 扫描所有路由,生成完整的 OpenAPI 文档
  3. SwaggerModule.setup() 把文档挂载到 /api 路径
Tip

createDocument() 用了工厂函数的方式,只有在你真正请求文档时才会生成。这样能节省启动时间。访问 /api-json 可以拿到 JSON 格式的文档,/api-yaml 拿 YAML 格式。

标注 DTO 模型

光启动 Swagger 还不够,它不知道你的请求体和返回值长什么样。你需要用 @ApiProperty() 装饰器来标注 DTO 的每个字段。

import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';

export class CreateCatDto {
  @ApiProperty({ description: '猫咪的名字', example: '咪咪' })
  name: string;

  @ApiProperty({ description: '猫咪的年龄', example: 3, minimum: 0 })
  age: number;

  @ApiPropertyOptional({ description: '猫咪的品种', example: '橘猫' })
  breed?: string;
}

@ApiProperty() 常用的配置项:

配置项说明
description字段描述
example示例值
required是否必填(默认 true
minimum / maximum数值范围
minLength / maxLength字符串长度范围
enum枚举值列表
type字段类型(复杂类型时需要)
isArray是否是数组

如果字段是可选的,用 @ApiPropertyOptional(),效果跟 @ApiProperty({ required: false }) 一样。

Note

如果你用了 class-validator 的装饰器(比如 @IsString()@Min()),Swagger 插件可以自动从这些装饰器里提取信息,省去手写 @ApiProperty() 参数的工作。后面会讲这个插件。

标注控制器

DTO 标好了,接下来标注控制器里的接口:

import { Controller, Get, Post, Body, Param } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiParam } from '@nestjs/swagger';
import { CatDto } from './dto/cat.dto';
import { CreateCatDto } from './dto/create-cat.dto';

@ApiTags('cats') // 分组标签
@Controller('cats')
export class CatsController {
  @Post()
  @ApiOperation({ summary: '创建一只猫' })
  @ApiResponse({ status: 201, description: '创建成功', type: CatDto })
  @ApiResponse({ status: 400, description: '参数错误' })
  create(@Body() createCatDto: CreateCatDto): Promise<CatDto> {
    return this.catsService.create(createCatDto);
  }

  @Get(':id')
  @ApiOperation({ summary: '根据 ID 获取猫咪' })
  @ApiParam({ name: 'id', description: '猫咪 ID' })
  @ApiResponse({ status: 200, description: '查询成功', type: CatDto })
  findOne(@Param('id') id: string): Promise<CatDto> {
    return this.catsService.findOne(id);
  }
}

常用的控制器装饰器:

装饰器作用用在哪
@ApiTags()接口分组标签控制器 / 方法
@ApiOperation()接口描述(summary)方法
@ApiResponse()描述响应状态和类型方法 / 控制器
@ApiParam()描述路径参数方法 / 控制器
@ApiQuery()描述查询参数方法 / 控制器
@ApiBody()描述请求体方法
@ApiHeader()描述请求头方法 / 控制器
@ApiExcludeEndpoint()排除某个接口方法
@ApiExcludeController()排除整个控制器控制器

认证配置

如果你的接口需要认证,Swagger 文档里也要体现出来。

Bearer Token

const config = new DocumentBuilder()
  .setTitle('猫咪 API')
  .addBearerAuth() // 添加 Bearer Token 认证
  .build();

然后在需要认证的控制器或方法上加装饰器:

@ApiBearerAuth()
@Controller('cats')
export class CatsController {
  // 这个控制器下的所有接口都会显示需要 Bearer Token
}

其他认证方式

DocumentBuilder 还支持其他认证方式:

const config = new DocumentBuilder()
  .addBasicAuth()     // HTTP Basic 认证
  .addCookieAuth()    // Cookie 认证
  .addOAuth2()        // OAuth2 认证
  .addApiKey()        // API Key 认证
  .build();

对应的装饰器:

@ApiBasicAuth()     // 方法/控制器级别
@ApiCookieAuth()
@ApiOAuth2()
@ApiSecurity('api_key')

自动生成的 Swagger 插件

每次都要手动写 @ApiProperty() 的参数,挺烦的。NestJS 提供了一个编译器插件,能自动从代码里提取信息。

配置

nest-cli.json 里启用:

{
  "compilerOptions": {
    "plugins": ["@nestjs/swagger"]
  }
}

启用后,插件会自动做这些事:

  • @ApiProperty() 标注的字段类型推断 type,不用手动写
  • 从 class-validator 装饰器(@IsString()@Min() 等)提取校验规则
  • 根据字段名和类型自动生成 description
  • 可选字段(带 ?)自动标记为 required: false

这意味着你的 DTO 可以写得更简洁:

// 不用插件时
@ApiProperty({ type: String, description: '猫咪的名字' })
name: string;

// 用了插件后
@ApiProperty({ description: '猫咪的名字' })
name: string; // type 自动推断为 String
Tip

插件还支持自定义配置,比如设置 dtoFileNameSuffixcontrollerFileNameSuffix 等。详细配置可以参考 @nestjs/swagger 的文档。

文档选项

createDocument() 的第三个参数可以精细控制文档生成行为:

const documentFactory = () =>
  SwaggerModule.createDocument(app, config, {
    include: [CatsModule],          // 只包含指定模块
    ignoreGlobalPrefix: true,       // 忽略全局前缀
    deepScanRoutes: true,           // 深度扫描路由
    autoTagControllers: true,       // 自动根据控制器名生成标签
    operationIdFactory: (controllerKey, methodKey) => methodKey, // 自定义 operationId
  });

几个实用的选项:

选项说明
include只生成指定模块的文档
ignoreGlobalPrefix忽略 setGlobalPrefix() 设置的前缀
deepScanRoutes深度扫描 include 模块导入的子模块路由
extraModels额外包含的模型(不在路由里但想出现在文档里的)
autoTagControllers自动用控制器名(去掉 Controller 后缀)作为标签

UI 定制

SwaggerModule.setup() 的第四个参数可以定制 Swagger UI 的外观和行为:

SwaggerModule.setup('api', app, documentFactory, {
  customSiteTitle: '猫咪 API 文档',     // 网页标题
  customFavIcon: '/favicon.ico',        // 网站图标
  customCss: '.swagger-ui .topbar { display: none }', // 自定义 CSS
  swaggerOptions: {
    persistAuthorization: true,          // 刷新页面保留认证信息
    docExpansion: 'list',               // 默认展开级别:none/list/full
  },
});

常用的 UI 配置:

选项说明
customSiteTitle网页标题
customFavIcon网站图标 URL
customCss自定义 CSS 样式
customJs自定义 JS 文件
swaggerOptionsSwagger UI 原生配置
useGlobalPrefix是否使用全局前缀
ui设为 false 关闭 UI(只保留 JSON/YAML)
raw控制 JSON/YAML 文档的暴露
Tip

persistAuthorization: true 这个选项很实用。默认情况下,你刷新页面后填好的 Token 就没了。开了这个选项后,Token 会保存在浏览器里。

隐藏接口和字段

有些接口不想暴露在文档里(比如内部调试用的),用 @ApiExcludeEndpoint() 就行:

@Get('debug')
@ApiExcludeEndpoint() // 这个接口不会出现在 Swagger 文档里
debug() {
  return 'debug info';
}

DTO 里有些字段不想暴露,用 @ApiHideProperty()

export class UserDto {
  @ApiProperty()
  name: string;

  @ApiHideProperty()
  password: string; // 不会出现在文档里
}

多个文档版本

如果你的 API 有多个版本(v1、v2),可以生成多份文档:

const configV1 = new DocumentBuilder()
  .setTitle('API v1')
  .setVersion('1.0')
  .build();

const configV2 = new DocumentBuilder()
  .setTitle('API v2')
  .setVersion('2.0')
  .build();

const documentV1 = () => SwaggerModule.createDocument(app, configV1, {
  include: [V1Module],
});

const documentV2 = () => SwaggerModule.createDocument(app, configV2, {
  include: [V2Module],
});

SwaggerModule.setup('api/v1', app, documentV1);
SwaggerModule.setup('api/v2', app, documentV2);

导出文档

除了在线查看,你还可以把文档导出为 JSON 或 YAML 文件:

import * as fs from 'fs';

const document = SwaggerModule.createDocument(app, config);
fs.writeFileSync('./swagger-doc.json', JSON.stringify(document, null, 2));

访问 /api-json 也能直接下载 JSON 格式的文档。

Tip

踩坑经验:如果用了 helmet 中间件,Swagger UI 可能会因为 CSP(内容安全策略)加载不出来。解决方法是调整 CSP 配置:

app.register(helmet, {
  contentSecurityPolicy: {
    directives: {
      styleSrc: ["'self'", "'unsafe-inline'"],
      imgSrc: ["'self'", 'data:', 'validator.swagger.io'],
      scriptSrc: ["'self'", 'https:', "'unsafe-inline'"],
    },
  },
});

装饰器速查表

装饰器作用用在哪
@ApiTags()分组标签控制器/方法
@ApiOperation()接口描述方法
@ApiResponse()响应描述方法/控制器
@ApiParam()路径参数方法/控制器
@ApiQuery()查询参数方法/控制器
@ApiBody()请求体方法
@ApiHeader()请求头方法/控制器
@ApiProperty()模型属性模型
@ApiPropertyOptional()可选模型属性模型
@ApiHideProperty()隐藏模型属性模型
@ApiBearerAuth()Bearer 认证方法/控制器
@ApiBasicAuth()Basic 认证方法/控制器
@ApiCookieAuth()Cookie 认证方法/控制器
@ApiOAuth2()OAuth2 认证方法/控制器
@ApiExcludeEndpoint()排除接口方法
@ApiExcludeController()排除控制器控制器
@ApiExtraModels()额外模型方法/控制器
@ApiConsumes()请求 Content-Type方法/控制器
@ApiProduces()响应 Content-Type方法/控制器
@ApiSecurity()安全方案方法/控制器
@ApiExtension()自定义扩展方法
@ApiCallbacks()回调定义方法/控制器
@ApiSchema()Schema 配置模型

小结

本章覆盖了 NestJS 集成 Swagger/OpenAPI 的核心内容:

  • 安装 @nestjs/swagger,在 main.ts 里几行代码就能启动
  • @ApiProperty() 标注 DTO 模型,让文档知道字段长什么样
  • @ApiOperation()@ApiResponse() 等标注控制器
  • DocumentBuilder 配置认证(Bearer、Basic、OAuth2 等)
  • Swagger 编译器插件能自动提取类型和校验信息
  • 可以定制 UI 外观、隐藏接口、导出文档
  • 支持多版本文档

有了 Swagger,你的 API 就有了自动更新的交互式文档。前端同事可以自己看文档、调试接口,再也不用追着你问了。