如何使用 Swagger UI 和 JSDoc 编写 Express API 文档

2025-05-25

如何使用 Swagger UI 和 JSDoc 编写 Express API 文档

JSDoc是一款流行的工具,可以根据应用源代码中的注释生成文档。这有两个目的。首先,任何查看源代码的人都可以直接访问该文档。其次,注释稍后可以编译成一套完整的参考文档。

Swagger提供了一个用于呈现此类文档的工具:Swagger UI。Swagger UI 根据OpenAPI 规范定义创建网页。正如本教程所示,这些定义可以直接以 YAML 格式写入 JSDoc 注释中。

在本教程中,您将为 Express API 设置一个Swagger UI文档网页。然后,您可以在 API 源代码中编写 JSDoc 注释来生成 OpenAPI 定义。最后,您将获得遵循 OpenAPI 规范的文档,并通过/docs添加到 Express API 的自定义端点呈现:

Swagger UI 文档页面

先决条件

要完成本教程,您需要

要安装和运行示例 Express API,首先克隆存储库(替换test-api为您选择的目录名称):



git clone https://github.com/kabartolo/jsonplaceholder-express-api test-api


Enter fullscreen mode Exit fullscreen mode

接下来运行以下命令启动 Express 服务器(替换test-api为刚刚创建的目录的名称):



cd test-api
npm install
npm run start


Enter fullscreen mode Exit fullscreen mode

导航localhost:3000以查看 API。您应该会看到/users和 的链接/users/1

API主页

导航到其中任何一个即可查看来自 JSONPlaceholder 的用户数据。

本教程中添加的代码可以在存储库的docs分支中找到。

术语

OpenAPI是该规范的名称,而Swagger是实现该规范的工具集。请参阅Swagger 和 OpenAPI 之间有什么区别?

本教程使用OpenAPI定义的以下 API 相关术语和定义



    https://api.example.com/v1/users?role=admin&status=active
    \________________________/\____/ \______________________/
             server URL       endpoint    query parameters
                                path


Enter fullscreen mode Exit fullscreen mode
  • 服务器 URL 或基本 URL:所有 API 端点的基本 URL:localhost:3000example.com/api
  • 端点路径:表示资源位置的路径(相对于基本 URL):/users/users/1
  • 操作:用于操作端点路径的 HTTP 方法:GET、POST、PUT、DELETE
  • Resource:表示现实世界对象(例如,用户或书籍)的信息,通常由 API 以 JSON 数据形式返回。在 Express 中,由数据库模型表示。

用于从 API 检索数据的完整 URL 是通过将端点添加到基本 URL 形成的:localhost:3000/users

步骤 1:设置应用程序

1.1:安装swagger-jsdocswagger-ui-express

要从 JSDoc 注释创建 Swagger UI 页面,您需要一种方法将文档传递给 Swagger UI:

要安装swagger-jsdocswagger-ui-express运行 Express API,请运行



npm install swagger-jsdoc@5.0.1 --save-exact
npm install swagger-ui-express --save


Enter fullscreen mode Exit fullscreen mode

本教程使用swagger-jsdoc版本5.0.1。最新版本可能与本教程不兼容。

1.2:创建 API 规范

Swagger UI 根据一组 OpenAPI 定义创建文档页面。这些定义以YAMLJSON格式编写,用于描述 REST API。有关 OpenAPI 规范基本结构的更多信息,请参阅基本结构

在您的 Express APIapp.js文件中,在所需模块列表下方添加以下代码:



// app.js
const swaggerJSDoc = require('swagger-jsdoc');

const swaggerDefinition = {
  openapi: '3.0.0',
  info: {
    title: 'Express API for JSONPlaceholder',
    version: '1.0.0',
  },
};

const options = {
  swaggerDefinition,
  // Paths to files containing OpenAPI definitions
  apis: ['./routes/*.js'],
};

const swaggerSpec = swaggerJSDoc(options);


Enter fullscreen mode Exit fullscreen mode

swaggerDefinition对象(即 OpenAPI 定义)定义了 API 的根信息。请向 提供一些基本信息swaggerDefinition,例如API 的titleversion;您可以稍后填写更多信息。

options对象包含此swaggerDefinition对象和一个名为 的路径数组apis。这些路径指向包含其他 OpenAPI 定义的文件。这些文件路径应相对于 Express API 的根目录。在本例中,定义将直接以 JSDoc 格式写入文件中/routes。您可以单独列出文件名,也可以使用通配符分隔符*添加目录中的所有 JavaScript 文件,如上所示。

options对象用于swagger-jsdoc在名为 的变量中生成 OpenAPI 规范swaggerSpec。此规范相当于Swagger UI 通常用于创建文档页面的swagger.jsonswagger.yaml文件。您将在下一步中将此对象传递给 Swagger UI。

重启Express 服务器以确保没有错误。如果在此阶段遇到任何错误,请检查您的swagger-jsdoc版本是否5.0.1完全一致。

1.3:创建 Swagger UI 文档页面

要为您的 Express API 创建 Swagger UI 页面,请将其包含swagger-ui-express在文件中。然后,添加一个名为(或您选择的任何名称)app.js的端点路径:/docs



// app.js
// ...
const swaggerJSDoc = require('swagger-jsdoc');
const swaggerUi = require('swagger-ui-express');

// ...

var app = express();

app.use('/docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));


Enter fullscreen mode Exit fullscreen mode

如上所示,swagger-ui-express提供两个回调来设置端点:一个用于使用定义设置Swagger UI swaggerSpec,另一个用于将提供/docs给端点。

重新启动Express 服务器,并在浏览器中导航至。localhost:3000/docs

您将看到 Express API 的标题和版本号,以及 OpenAPI 版本号 ( 3.0.0)。由于我们还没有其他定义,您将看到“规范中未定义任何操作!”消息:

基本 Swagger UI 页面

现在,您已经为 API 创建了一个漂亮的文档页面!本教程的其余部分将提供 OpenAPI 定义的基本介绍。

第 2 步:定义 API 的根信息

您已创建 Swagger UI 文档页面,现在就可以开始编写文档了。但首先,您需要为 API 添加更多根定义。

返回app.js。请注意,该info对象映射到 OpenAPI 的信息对象,以定义 API 的标题、描述、服务器列表、联系信息和路径列表。

以下是更完整定义的示例:



// app.js
const swaggerDefinition = {
  openapi: '3.0.0',
  info: {
    title: 'Express API for JSONPlaceholder',
    version: '1.0.0',
    description:
      'This is a REST API application made with Express. It retrieves data from JSONPlaceholder.',
    license: {
      name: 'Licensed Under MIT',
      url: 'https://spdx.org/licenses/MIT.html',
    },
    contact: {
      name: 'JSONPlaceholder',
      url: 'https://jsonplaceholder.typicode.com',
    },
  },
  servers: [
    {
      url: 'http://localhost:3000',
      description: 'Development server',
    },
  ],
};


Enter fullscreen mode Exit fullscreen mode

如果您有生产服务器,请将 URL 和说明添加到servers列表中。有关可添加到根定义的其他属性的更多信息,请参阅基本结构。

OpenAPI 文档中,您会注意到还有一个paths字段。您无需在此处指定路径定义,因为每个路径都在 JSDoc 注释中单独定义(将在下一步添加)。这些路径定义会被编译swagger-jsdoc成一个paths对象。

重启Express 服务器,然后再次在浏览器中导航localhost:3000/docs到。你应该会在文档页面顶部看到更多关于你的 API 的信息:

包含 API 信息的 Swagger UI 页面

您现在可以开始记录您的 Express 路线。

步骤 3:编写文档

有了端点上可用的 Swagger UI 文档页面/docs以及 API 的完整根信息,您就可以开始编写路径定义。每个路径定义都对应 API 中的一个 Express 路由。它描述了操作和端点路径,例如GET /usersDELETE /users/:id

3.1:记录路线

要记录/routes/users.js,首先在第一个路由上方添加以 开头的注释@swagger。然后添加一些关于该路由的基本信息:



// routes/users.js

/**
 * @swagger
 * /users:
 *   get:
 *     summary: Retrieve a list of JSONPlaceholder users
 *     description: Retrieve a list of users from JSONPlaceholder. Can be used to populate a list of fake users when prototyping or testing an API.
*/
router.get('/', function(req, res) {
  //...
});


Enter fullscreen mode Exit fullscreen mode

请注意,swagger-jsdoc查找带有@swagger@openapi标签的注释来创建 OpenAPI 定义。

如代码示例所示,添加端点路径/users和操作get(缩进两个空格)。Express 路由器函数中的路径get('/')是相对于 的/users,因此定义中的路径应该是/users

应该summary简要描述此路线的目标。description应该提供更多详细信息,例如何时或为何要使用此路线。

请务必使用两个空格(或四个空格)来缩进,而不是使用制表符。有关更多信息,请参阅YAML 语法。

重启Express 服务器,然后再次在浏览器中导航到 。你应该会在页面底部看到一个列表:localhost:3000/docsGET /users

Swagger UI 页面显示第一条路径

3.2:记录回复

您的用户可能想知道此 GET 请求成功后会返回什么(即状态码为200)。要定义成功响应,请在路径定义中添加一个responses对象和一个名为 的响应:200



// routes/users.js

/**
 * @swagger
 * /users:
 *   get:
 *     summary: Retrieve a list of JSONPlaceholder users.
 *     description: Retrieve a list of users from JSONPlaceholder. Can be used to populate a list of fake users when prototyping or testing an API.
 *     responses:
 *       200:
 *         description: A list of users.
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 data:
 *                   type: array
 *                   items:
 *                     type: object
 *                     properties:
 *                       id:
 *                         type: integer
 *                         description: The user ID.
 *                         example: 0
 *                       name:
 *                         type: string
 *                         description: The user's name.
 *                         example: Leanne Graham
 */
router.get('/', function(req, res) {
  //...
});


Enter fullscreen mode Exit fullscreen mode

字段description描述响应或返回的内容。content字段描述内容类型(application/json),而schema描述响应对象。在我们的例子中,JSONPlaceholder 返回一个带有data字段的对象,该字段包含您请求的数据。对于此响应,data包含一个用户对象数组。目前只需添加一两个用户属性(例如id和),以避免文件混乱。name

为每个属性添加一个真实示例值(例如'Leanne Graham');否则,Swagger UI 会创建一个通用示例,例如'string'

注意此架构中类型的定义方式。例如,要定义一个数组,请添加type: array一个items字段。有关类型的更多信息,请参阅数据类型文档。

您也可以通过这种方式描述错误响应。有关可用于描述每个响应的字段的更多详细信息,请参阅 Swagger 的“描述响应”文档。

重启Express 服务器,然后再次在浏览器中导航localhost:3000/docs到。您应该会看到响应、一个示例值(使用您为每个属性提供的示例值)以及此响应中返回的数据的架构:

响应和模式

接下来,GET /users/:id通过添加我们已经介绍过的字段(summarydescriptionresponses)来定义路径:



// routes/users.js

 /**
 * @swagger
 * /users/{id}:
 *   get:
 *     summary: Retrieve a single JSONPlaceholder user.
 *     description: Retrieve a single JSONPlaceholder user. Can be used to populate a user profile when prototyping or testing an API.
 *     responses:
 *       200:
 *         description: A single user.
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 data:
 *                   type: object
 *                   properties:
 *                     id:
 *                       type: integer
 *                       description: The user ID.
 *                       example: 0
 *                     name:
 *                       type: string
 *                       description: The user's name.
 *                       example: Leanne Graham
*/

router.get('/:id', function(req, res) {
  //...
});


Enter fullscreen mode Exit fullscreen mode

这里,路径参数 ( id) 被添加到端点路径:/users/{id}。花括号 ( {}) 用于标记端点路径中的路径参数。请注意,冒号样式 ( /users/:id) 不适用于 Swagger(感谢@sherwinwater指出这一点!)。

data这里的对象包含schema单个用户对象而不是用户对象数组,但属性是相同的。

接下来,POST /users通过添加我们已经介绍过的字段(summarydescriptionresponses)来定义:



// routes/users.js

/**
 * @swagger
 * /users:
 *   post:
 *     summary: Create a JSONPlaceholder user.
 *     responses:
 *       201:
 *         description: Created
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 data:
 *                   type: object
 *                   properties:
 *                     id:
 *                       type: integer
 *                       description: The user ID.
 *                       example: 0
 *                     name:
 *                       type: string
 *                       description: The user's name.
 *                       example: Leanne Graham
*/
router.post('/', function(req, res) {
// ...
});


Enter fullscreen mode Exit fullscreen mode

在这种情况下,成功的响应将是201。它返回一个带有data包含新用户的字段的对象。

您可以继续以相同的方式为其余路由添加路径定义。我们将在后续步骤中进行一些重构。

重启Express 服务器,然后在浏览器中再次导航到 。现在您将看到、以及您添加的任何其他路径定义localhost:3000/docs的列表:GET /users/{id}POST /users

Swagger UI 文档页面

3.3:记录请求

请求数据(例如参数和请求主体)也可以记录在 OpenAPI 定义中。例如,GET /users/:id有一个id参数,就应该记录下来。

要记录参数,parameters请向路径定义添加一个字段:



// routes/users.js

/**
 * @swagger
 * /users/{id}:
 *   get:
 *     summary: Retrieve a single JSONPlaceholder user.
 *     description: Retrieve a single JSONPlaceholder user. Can be used to populate a user profile when prototyping or testing an API.
 *     parameters:
 *       - in: path
 *         name: id
 *         required: true
 *         description: Numeric ID of the user to retrieve.
 *         schema:
 *           type: integer
 *     responses:
 *       200:
 *         ...
 */
router.get('/:id', function(req, res) {
  //...
});



Enter fullscreen mode Exit fullscreen mode

在此参数的定义中,in定义参数的位置(在本例中,它是一个路径参数,因为它是路径的一部分)。您还可以添加namedescription和 ,schema以及参数是否required。有关更多详细信息,请参阅描述参数

重启Express 服务器,然后再次在浏览器中导航localhost:3000/docs到。您将看到此路由的参数列表:

路由参数

接下来,记录请求主体,以POST /users描述在数据库中创建新用户所需的数据。为此,请向以下路径定义添加一个字段:requestBody



// routes/users.js

/**
 * @swagger
 * /users:
 *   post:
 *     summary: Create a JSONPlaceholder user.
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             properties:
 *               name:
 *                 type: string
 *                 description: The user's name.
 *                 example: Leanne Graham
 *     responses:
 *       201:
 *         ...
*/
router.post('/', function(req, res) {
// ...
});


Enter fullscreen mode Exit fullscreen mode

这会将请求体架构添加到此路径定义中。此示例显示name可以在请求体中发送。您可以稍后为新用户添加更多属性。有关更多详细信息,请参阅描述请求体。

重启Express 服务器,然后再次在浏览器中导航到 。你会看到一个名为 的部分,其中包含你提供的架构:localhost:3000/docsRequest body

请求正文

3.4:记录资源

您可能已经注意到,到目前为止,您在文档中已经多次重复了用户架构。为了避免这种重复,您可以在一个地方定义用户架构,然后在其他地方引用它。

Express API 定义的每个模型都可以单独记录为一个 Schema 定义(或组件)。对于用户模型,请User在文件顶部的 下添加一个 Schema 定义components/schemas



// routes/users.js

/**
 * @swagger
 * components:
 *   schemas:
 *     User:
 *       type: object
 *       properties:
 *         id:
 *           type: integer
 *           description: The user ID.
 *           example: 0
 *         name:
 *           type: string
 *           description: The user's name.
 *           example: Leanne Graham
 */


Enter fullscreen mode Exit fullscreen mode

然后,您可以使用以下方式引用该架构定义$ref



// routes/users.js

/**
 * @swagger
 * /users:
 *   get:
 *     summary: Retrieve a list of JSONPlaceholder users
 *     description: Retrieve a list of users from JSONPlaceholder. Can be used to populate a list of fake users when prototyping or testing an API.
 *     responses:
 *       200:
 *         description: A list of users.
 *         content:
 *           application/json:
 *             schema:
 *               type: array
 *               items:
 *                 $ref: '#/components/schemas/User'
 */
router.get('/', function(req, res) {
  //...
});


Enter fullscreen mode Exit fullscreen mode

$ref路径使用JSON 引用表示法。该#符号指示当前文档的根,其余嵌套值随后按顺序解析。有关更多信息,请参阅使用 $ref

重启Express 服务器,然后在浏览器中再次导航到 。你的路径定义现在将使用此架构,你应该在页面底部看到 的架构定义:localhost:3000/docsUserUser

用户架构

类似地,您可以定义一个NewUser对象在请求主体中引用POST /users。由于它包含模式中的部分字段(但不是全部)User,因此您也可以使用它$ref来避免它们之间的重复:



/**
 * @swagger
 * components:
 *   schemas:
 *     NewUser:
 *       type: object
 *       properties:
 *         name:
 *           type: string
 *           description: The user's name.
 *           example: Leanne Graham
 *     User:
 *       allOf:
 *         - type: object
 *           properties:
 *             id:
 *               type: integer
 *               description: The user ID.
 *               example: 0
 *         - $ref: '#/components/schemas/NewUser'
 */


Enter fullscreen mode Exit fullscreen mode

allOf关键字将模型定义(在本例中NewUser为包含name属性的定义)与具有属性的对象连接起来id更多详情请参阅oneOf、anyOf、allOf 和 not 。

您现在可以NewUser从请求主体定义中引用POST /users



/**
 * @swagger
 * /users:
 *   post:
 *     summary: Create a JSONPlaceholder user.
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             $ref: '#/components/schemas/NewUser'
 *     responses:
 *       201:
 *         ...
*/
router.post('/', function(req, res) {
  // ...
});


Enter fullscreen mode Exit fullscreen mode

重启Express 服务器,然后在浏览器中再次导航到 。您将在 的请求正文定义中localhost:3000/docs看到您的架构NewUserPOST /users

新用户架构
这涵盖了在 JSDoc 注释中生成 OpenAPI 定义的基本技术。

结论

现在,您已准备好为您的 Express API 生成完整的参考文档页面。您已创建一组基本的 OpenAPI 定义和一个显示这些定义的 Swagger UI 页面。如果您想进一步练习 OpenAPI 规范,可以完成文档的编写jsonplaceholder-express-api

本教程还介绍了编写 OpenAPI 定义的基础知识。要完善您的文档,请参阅OpenAPI 规范Swagger 文档

要查看包含本教程中添加的所有代码的版本jsonplaceholder-express-api,请参阅存储库的docs分支

文章来源:https://dev.to/kabartolo/how-to-document-an-express-api-with-swagger-ui-and-jsdoc-50do
PREV
每位开发者必知的 11 个免费网站
NEXT
改变我人生的 7 个 Vim 技巧(附演示)