基于OpenAPI规范的API文档。swagger介绍。

前言

编写目的

本文介绍如何使用Swagger编写API文档。通过阅读本文,你可以:

  • 了解swagger是什么
  • 掌握使用swagger编写API文档的基本方法

涉及范围

  • 本文包括对swagger specification(以下译作”规范“)的介绍,如何使用swaager协议编写出功能完整、结构清晰的API文档,以及项目实践中需要注意的问题。

  • swagger的生态完整,从文档生成、编辑、测试到各种语言的代码自动生成,都有很多开源工具支持。本文中不介绍这些工具的使用。


第1章 简介

1.1 Swagger

The World's Most Popular Framework for APIs.

Starting January 1st 2016 the Swagger Specification has been donated(捐赠) to the Open API Initiative (OAI) and is the foundation of the OpenAPI Specification.

Swagger(丝袜哥)给人第一印象就是【最(hen)流(niu)行(bai)】,不懂Swagger咱就out了。它的官方网站是http://swagger.io/。

Swagger是一个简单但功能强大的API表达工具。它具有地球上最大的API工具生态系统,数以千计的开发人员,使用几乎所有的现代编程语言,都在支持和使用Swagger。使用Swagger生成API,我们可以得到交互式文档,自动生成代码的SDK以及API的发现特性等。

现在,Swagger已经帮助包括Apigee, Getty图像, Intuit, LivingSocial, McKesson, 微软, Morningstar和PayPal等世界知名企业建立起了一套基于RESTful API的完美服务系统。

2.0版本已经发布,Swagger变得更加强大。值得感激的是,Swagger的源码100%开源在github。

1.2 OpenAPI规范

OpenAPI规范是Linux基金会的一个项目,试图通过定义一种用来描述API格式或API定义的语言,来规范RESTful服务开发过程。OpenAPI规范帮助我们描述一个API的基本信息,比如:

  • 有关该API的一般性描述
  • 可用路径(/资源)
  • 在每个路径上的可用操作(获取/提交...)
  • 每个操作的输入/输出格式

目前V2.0版本的OpenAPI规范(也就是SwaggerV2.0规范)已经发布并开源在github上。该文档写的非常好,结构清晰,方便随时查阅。关于规范的学习和理解,本文最后还有个彩蛋。

1.3 为啥要使用OpenAPI规范?

  • OpenAPI规范这类API定义语言能够帮助你更简单、快速的表述API,尤其是在API的设计阶段作用特别突出
  • 根据OpenAPI规范编写的二进制文本文件,能够像代码一样用任何VCS工具管理起来
  • 一旦编写完成,API文档可以作为:
    • 需求和系统特性描述的根据
    • 前后台查询、讨论、自测的基础
    • 部分或者全部代码自动生成的根据
    • 其他重要的作用,比如开放平台开发者的手册...

1.4 如何编写API文档?

1.4.1 语言:JSON vs YAML

我们可以选择使用JSON或者YAML的语言格式来编写API文档。但是个人建议使用YAML来写,原因是它更简单。一图胜千言,先看用JSON写的文档:


   
   
   
   
  1. {
  2. "swagger": "2.0",
  3. "info": {
  4. "version": "1.0.0",
  5. "title": "Simple API",
  6. "description": "A simple API to learn how to write OpenAPI Specification"
  7. },
  8. "schemes": [
  9. "https"
  10. ],
  11. "host": "simple.api",
  12. "basePath": "/openapi101",
  13. "paths": {
  14. "/persons": {
  15. "get": {
  16. "summary": "Gets some persons",
  17. "description": "Returns a list containing all persons.",
  18. "responses": {
  19. "200": {
  20. "description": "A list of Person",
  21. "schema": {
  22. "type": "array",
  23. "items": {
  24. "properties": {
  25. "firstName": {
  26. "type": "string"
  27. },
  28. "lastName": {
  29. "type": "string"
  30. },
  31. "username": {
  32. "type": "string"
  33. }
  34. }
  35. }
  36. }
  37. }
  38. }
  39. }
  40. }
  41. }
  42. }

再来看看同一份API文档的YAML实现:


   
   
   
   
  1. swagger: "2.0"
  2. info:
  3. version: 1.0 .0
  4. title: Simple API
  5. description: A simple API to learn how to write OpenAPI Specification
  6. schemes:
  7. - https
  8. host: simple.api
  9. basePath: /openapi101
  10. paths:
  11. /persons:
  12. get:
  13. summary: Gets some persons
  14. description: Returns a list containing all persons.
  15. responses:
  16. 200:
  17. description: A list of Person
  18. schema:
  19. type: array
  20. items:
  21. required:
  22. - username
  23. properties:
  24. firstName:
  25. type: string
  26. lastName:
  27. type: string
  28. username:
  29. type: string

对于普通人来说,似乎用YAML更能够简化书写和阅读。这里我们并没有非此即彼的选择问题,因为:

  • 几乎所用支持OpenAPI规范的工具都支持YAML
  • 有很多的工具可以实现YAML-JSON之间的转换

所以,用自己喜欢的方式书写即可。(后面的示例文档也都是用YAML来写的。强烈推荐使用YAML。)

1.4.2 编辑器

编写API文档,其实我们只是在写一个简单的文本文件。我们可以用任何最普通的文档编辑器来写。但是为了提高效率,还是建议使用专业的编辑工具。众多工具中,最好的选择是Swagger Editor,它能够提供语法高亮、自动完成、即时预览等功能,非常强大。

左边编辑API文档,右边实时预览。下面这张动图展示编辑提升功能:

我们可以使用在线版本来编辑,也可以非常简单的本地部署,更多细节请参考另一篇文档Swagger环境搭建.md以及Swagger Editor开源仓库上的说明。


第2章 从零开始

这一章主要介绍API的基本组成部分,包括提供给API消费者(所有可能访问API的个体,下简称“消费者”)的的不同HTTP请求方法、路径,请求和消息体中的参数,以及返回给消费者的不同HTTP状态及响应消息体。

2.1 最简单的例子

我们从一个最简单(几乎没有东西)的API文档开始:


   
   
   
   
  1. swagger: "2.0"
  2. info:
  3. version: 1.0 .0
  4. title: Simple API
  5. description: A simple API to learn how to write OpenAPI Specification
  6. schemes:
  7. - https
  8. host: simple.api
  9. basePath: /openapi101
  10. paths: {}

这个文档的内容分成四部分,下面分别来说明。

2.1.1 OpenAPI规范的版本号

首先我们要通过一个swagger属性来声明OpenAPI规范的版本。

swagger: "2.0"

   
   
   
   

你没看错,是swagger,上面已经介绍了,OpenAPI规范是基于Swagger的,在未来的版本中,这个属性可能会换成别的。 目前这个属性的值,暂时只能填写为2.0

2.1.2 API描述信息

然后我们需要说明一下API文档的相关信息,比如API文档版本(注意不同于上面的规范版本)、API文档名称已经可选的描述信息。


   
   
   
   
  1. info:
  2. version: 1.0. 0
  3. title: Simple API
  4. description: A simple API to learn how to write OpenAPI Specification

2.1.3 API的URL

作为web API,一个很重要的信息就是用来给消费者使用的根URL,可以用协议(http或者https)、主机名、根路径来描述:


   
   
   
   
  1. schemes:
  2. - https
  3. host: simple.api
  4. basePath: /openapi101

这这个例子中,消费者把https://simple.api/open101作为根节点来访问各种API。因为和具体环境有关,不涉及API描述的根本内容,所以这部分信息是可选的。

2.1.4 API的操作(operation)

这个例子中,我们没有写API的操作,用一个YAML的空对象{}先占个位置。

2.2 定义一个API操作

如果我们要展示一组用户信息,可以这样描述:


   
   
   
   
  1. swagger: "2.0"
  2. info:
  3. version: 1.0 .0
  4. title: Simple API
  5. description: A simple API to learn how to write OpenAPI Specification
  6. schemes:
  7. - https
  8. host: simple.api
  9. basePath: /openapi101
  10. paths:
  11. /persons:
  12. get:
  13. summary: Gets some persons
  14. description: Returns a list containing all persons.
  15. responses:
  16. 200:
  17. description: A list of Person
  18. schema:
  19. type: array
  20. items:
  21. required:
  22. - username
  23. properties:
  24. firstName:
  25. type: string
  26. lastName:
  27. type: string
  28. username:
  29. type: string

2.2.1 添加一个路径(path)

我们添加一个/persons路径,用来访问一组用户信息:


   
   
   
   
  1. paths:
  2. /persons:

2.2.2 在路径中添加一个HTTP方法

在每个路径中,我们可以添加任意的HTTP动词来操作所需要的资源。

比如需要展示一组用户信息,我们可以在/persons路径中添加get方法,同时还可以填写一些简单的描述信息(summary)或者说明该方法的一段长篇大论(description)。


   
   
   
   
  1. get:
  2. summary: Gets some persons
  3. description: Returns a list containing all persons.

这样一来,我们调 get https://simple.api/open101/persons方法就能获取一个用户信息列表了。

2.2.3 定义响应(response)类型

对于每个方法(或操作),我们都可以在响应(responses)中添加任意的HTTP状态码(比如200 OK 或者 404 Not Found等)。这个例子中我们添加上200的响应:


   
   
   
   
  1. responses:
  2. 200:
  3. description: A list of Person

2.2.4 定义响应内容

get /persons这个接口返回一组用户信息,我们通过响应消息中的模式(schema)属性来描述清楚具体的返回内容。

一组用户信息就是一个用户信息对象的数组(array),每一个数组元素则是一个用户信息对象(object),该对象包含三个string类型的属性:姓氏名字用户名,其中用户名必须提供(required)。


   
   
   
   
  1. schema:
  2. type: array
  3. items:
  4. required:
  5. - username
  6. properties:
  7. firstName:
  8. type: string
  9. lastName:
  10. type: string
  11. username:
  12. type: string

2.3 定义请求参数(query parameters)

用户太多,我们不想一股脑全部输出出来。这个时候,分页输出是个不错的选择,我们可以通过添加请求参数来实现。


   
   
   
   
  1. swagger: "2.0"
  2. info:
  3. version: 1.0 .0
  4. title: Simple API
  5. description: A simple API to learn how to write OpenAPI Specification
  6. schemes:
  7. - https
  8. host: simple.api
  9. basePath: /openapi101
  10. paths:
  11. /persons:
  12. get:
  13. summary: Gets some persons
  14. description: Returns a list containing all persons. The list supports paging.
  15. #START############################################################################
  16. parameters:
  17. - name: pageSize
  18. in: query
  19. description: Number of persons returned
  20. type: integer
  21. - name: pageNumber
  22. in: query
  23. description: Page number
  24. type: integer
  25. # END ############################################################################
  26. responses:
  27. 200:
  28. description: A list of Person
  29. schema:
  30. type: array
  31. items:
  32. required:
  33. - username
  34. properties:
  35. firstName:
  36. type: string
  37. lastName:
  38. type: string
  39. username:
  40. type: string

2.3.1 在get方法中增加请求参数

首先我们在 get 方法中增加一个参数属性:


   
   
   
   
  1. paths:
  2. /persons:
  3. get:
  4. summary: Gets some persons
  5. description: Returns a list containing all persons. The list supports paging.
  6. #START############################################################################
  7. parameters:
  8. # END ############################################################################

2.3.2 添加分页参数

在参数列表中,我们添加两个名字(name)分别叫做pageSizepageNumber的整型(integer)参数,并作简单描述:


   
   
   
   
  1. parameters:
  2. #START############################################################################
  3. - name: pageSize
  4. in: query
  5. description: Number of persons returned
  6. type: integer
  7. - name: pageNumber
  8. in: query
  9. description: Page number
  10. type: integer
  11. # END ##############################################################################
  12. responses:

这样一来,消费者就可以通过 get /persons?pageSize=20&pageNumber=2 来访问第2页的用户信息(不超过20条)了。

2.4 定义路径参数(path parameter)

有时候我们想要根据用户名来查找用户信息,这时我们需要增加一个接口操作,比如可以添加一个类似 /persons/{username} 的操作来获取用户信息。注意,{username} 是在请求路径中的参数。


   
   
   
   
  1. swagger: "2.0"
  2. info:
  3. version: 1.0 .0
  4. title: Simple API
  5. description: A simple API to learn how to write OpenAPI Specification
  6. schemes:
  7. - https
  8. host: simple.api
  9. basePath: /openapi101
  10. paths:
  11. /persons:
  12. get:
  13. summary: Gets some persons
  14. description: Returns a list containing all persons. The list supports paging.
  15. parameters:
  16. - name: pageSize
  17. in: query
  18. description: Number of persons returned
  19. type: integer
  20. - name: pageNumber
  21. in: query
  22. description: Page number
  23. type: integer
  24. responses:
  25. 200:
  26. description: A list of Person
  27. schema:
  28. type: array
  29. items:
  30. required:
  31. - username
  32. properties:
  33. firstName:
  34. type: string
  35. lastName:
  36. type: string
  37. username:
  38. type: string
  39. #START############################################################################
  40. /persons/{username}:
  41. get:
  42. summary: Gets a person
  43. description: Returns a single person for its username
  44. parameters:
  45. - name: username
  46. in: path
  47. required: true
  48. description: The person 's username
  49. type: string
  50. responses:
  51. 200:
  52. description: A Person
  53. schema:
  54. required:
  55. - username
  56. properties:
  57. firstName:
  58. type: string
  59. lastName:
  60. type: string
  61. username:
  62. type: string
  63. 404:
  64. description: The Person does not exists.
  65. # END ############################################################################

2.4.1 添加一个 get /persons/{username} 操作

首先我们在 /persons 路径后面,增加一个 /persons/{username} 的路径,并定义一个 get (操作)方法。


   
   
   
   
  1. swagger: "2.0"
  2. info:
  3. version: 1.0 .0
  4. title: Simple API
  5. description: A simple API to learn how to write OpenAPI Specification
  6. schemes:
  7. - https
  8. host: simple.api
  9. basePath: /openapi101
  10. paths:
  11. /persons:

   
   
   
   
  1. username:
  2. type: string
  3. #START############################################################################
  4. /persons/{username}:
  5. get:
  6. summary: Gets a person
  7. description: Returns a single person for its username
  8. # END ############################################################################

2.4.2 定义路径参数 username

因为 {username} 是路径参数,我们需要先像请求参数一样将它添加到 parameters 属性中,注意名称应该同上面大括号( { } ) 里面的名称一致。并通过 in 这个属性,来表示它是一个路径(path)参数。


   
   
   
   
  1. parameters:
  2. - name: username
  3. in: path
  4. required: true
  5. description: The person 's username
  6. type: string

定义路径参数时很容易出现的问题就是忘记:required: true,Swagger的自动完成功能中没有包含这个属性定义。 如果没有写 require 属性,默认值是 false,也就是说 username 参数时可选的。可事实上,作为路径参数,它是必需的。

2.4.3 定义响应消息

别忘了获取单个用户信息也需要填写 200 响应消息,响应消息体的内容就是之前描述过的用户信息(用户信息列表中的一个元素):


   
   
   
   
  1. responses:
  2. 200:
  3. description: A Person
  4. schema:
  5. required:
  6. - username
  7. properties:
  8. firstName:
  9. type: string
  10. lastName:
  11. type: string
  12. username:
  13. type: string

当然,API的提供者会对 username 进行校验,如果查无此人,应该返回 404 的异常状态。所以我们再加上 404 状态的响应:


   
   
   
   
  1. 404:
  2. description: The Person does not exists.

2.5 定义消息体参数(body parameter)

当我们需要添加一个用户信息时,我们需要一个能够提供 post /persons 的API操作。


   
   
   
   
  1. swagger: "2.0"
  2. info:
  3. version: 1.0 .0
  4. title: Simple API
  5. description: A simple API to learn how to write OpenAPI Specification
  6. schemes:
  7. - https
  8. host: simple.api
  9. basePath: /openapi101
  10. paths:
  11. /persons:
  12. get:
  13. summary: Gets some persons
  14. description: Returns a list containing all persons. The list supports paging.
  15. parameters:
  16. - name: pageSize
  17. in: query
  18. description: Number of persons returned
  19. type: integer
  20. - name: pageNumber
  21. in: query
  22. description: Page number
  23. type: integer
  24. responses:
  25. 200:
  26. description: A list of Person
  27. schema:
  28. type: array
  29. items:
  30. required:
  31. - username
  32. properties:
  33. firstName:
  34. type: string
  35. lastName:
  36. type: string
  37. username:
  38. type: string
  39. #START############################################################################
  40. post:
  41. summary: Creates a person
  42. description: Adds a new person to the persons list.
  43. parameters:
  44. - name: person
  45. in: body
  46. description: The person to create.
  47. schema:
  48. required:
  49. - username
  50. properties:
  51. firstName:
  52. type: string
  53. lastName:
  54. type: string
  55. username:
  56. type: string
  57. responses:
  58. 204:
  59. description: Persons succesfully created.
  60. 400:
  61. description: Persons couldn 't have been created.
  62. # END ############################################################################
  63. /persons/{username}:
  64. get:
  65. summary: Gets a person
  66. description: Returns a single person for its username.
  67. parameters:
  68. - name: username
  69. in: path
  70. required: true
  71. description: The person 's username
  72. type: string
  73. responses:
  74. 200:
  75. description: A Person
  76. schema:
  77. required:
  78. - username
  79. properties:
  80. firstName:
  81. type: string
  82. lastName:
  83. type: string
  84. username:
  85. type: string
  86. 404:
  87. description: The Person does not exists.

2.5.1 添加一个 post /persons 操作

首先在 /persons 路径下廷加一个 post 操作:


   
   
   
   
  1. paths:
  2. /persons:

   
   
   
   
  1. post:
  2. summary: Creates a person
  3. description: Adds a new person to the persons list.

2.5.2 定义消息体参数

接下来我们给 post 方法添加参数,通过 in 属性显式说明参数是在 body 中的。参数的定义参考 get /persons/{username} 的 200 响应消息体参数,也就是包含用户的姓氏、名字、用户名。


   
   
   
   
  1. parameters:
  2. - name: person
  3. in: body
  4. description: The person to create.
  5. schema:
  6. required:
  7. - username
  8. properties:
  9. firstName:
  10. type: string
  11. lastName:
  12. type: string
  13. username:
  14. type: string

2.5.3 定义响应消息

最后不要忘记定义 post 操作的响应消息。


   
   
   
   
  1. responses:
  2. 204:
  3. description: Persons succesfully created.
  4. 400:
  5. description: Persons couldn 't have been created.

第3章 文档瘦身

现在我们已经学会了编写API文档的基本方法。不过上面的例子中存在一些重复,这对于程序员的嗅觉来说,就是代码的“坏味道”。这一章我们一起学习如何通过抽取可重用的定义(definitions)来简化API文档。

3.1 简化数据模型

我们认真观察第2章最后输出的API文档,很容易发现 Person 的定义出现了三次,非常的不 DRY☹。


   
   
   
   
  1. swagger: "2.0"
  2. info:
  3. version: 1.0 .0
  4. title: Simple API
  5. description: A simple API to learn how to write OpenAPI Specification
  6. schemes:
  7. - https
  8. host: simple.api
  9. basePath: /openapi101
  10. paths:
  11. /persons:
  12. get:
  13. summary: Gets some persons
  14. description: Returns a list containing all persons. The list supports paging.
  15. parameters:
  16. - name: pageSize
  17. in: query
  18. description: Number of persons returned
  19. type: integer
  20. - name: pageNumber
  21. in: query
  22. description: Page number
  23. type: integer
  24. responses:
  25. 200:
  26. description: A list of Person
  27. schema:
  28. type: array
  29. items:
  30. #START 第 1次定义###################################################################
  31. required:
  32. - username
  33. properties:
  34. firstName:
  35. type: string
  36. lastName:
  37. type: string
  38. username:
  39. type: string
  40. # END1次定义###################################################################
  41. post:
  42. summary: Creates a person
  43. description: Adds a new person to the persons list.
  44. parameters:
  45. - name: person
  46. in: body
  47. description: The person to create.
  48. schema:
  49. #START 第 2次定义###################################################################
  50. required:
  51. - username
  52. properties:
  53. firstName:
  54. type: string
  55. lastName:
  56. type: string
  57. username:
  58. type: string
  59. # END2次定义###################################################################
  60. responses:
  61. 204:
  62. description: Persons succesfully created.
  63. 400:
  64. description: Persons couldn 't have been created.
  65. /persons/{username}:
  66. get:
  67. summary: Gets a person
  68. description: Returns a single person for its username.
  69. parameters:
  70. - name: username
  71. in: path
  72. required: true
  73. description: The person 's username
  74. type: string
  75. responses:
  76. 200:
  77. description: A Person
  78. schema:
  79. #START 第 3次定义###################################################################
  80. required:
  81. - username
  82. properties:
  83. firstName:
  84. type: string
  85. lastName:
  86. type: string
  87. username:
  88. type: string
  89. # END3次定义###################################################################
  90. 404:
  91. description: The Person does not exists.

现在,我们通过可重用的定义 (definition)来重构这个文档:


   
   
   
   
  1. swagger: "2.0"
  2. info:
  3. version: 1.0.0
  4. title: Simple API
  5. description: A simple API to learn how to write OpenAPI Specification
  6. schemes:
  7. - https
  8. host: simple.api
  9. basePath: /openapi101
  10. paths:
  11. /persons:
  12. get:
  13. summary: Gets some persons
  14. description: Returns a list containing all persons. The list supports paging.
  15. parameters:
  16. - name: pageSize
  17. in: query
  18. description: Number of persons returned
  19. type: integer
  20. - name: pageNumber
  21. in: query
  22. description: Page number
  23. type: integer
  24. responses:
  25. 200:
  26. description: A list of Person
  27. schema:
  28. #START############################################################################
  29. $ref: "#/definitions/Persons"
  30. # END ############################################################################
  31. post:
  32. summary: Creates a person
  33. description: Adds a new person to the persons list.
  34. parameters:
  35. - name: person
  36. in: body
  37. description: The person to create.
  38. schema:
  39. #START############################################################################
  40. $ref: "#/definitions/Person"
  41. # END ############################################################################
  42. responses:
  43. 204:
  44. description: Persons succesfully created.
  45. 400:
  46. description: Persons couldn 't have been created.
  47. /persons/{username}:
  48. get:
  49. summary: Gets a person
  50. description: Returns a single person for its username.
  51. parameters:
  52. - name: username
  53. in: path
  54. required: true
  55. description: The person's username
  56. type: string
  57. responses:
  58. 200:
  59. description: A Person
  60. schema:
  61. #START############################################################################
  62. $ref: "#/definitions/Person"
  63. # END ############################################################################
  64. 404:
  65. description: The Person does not exists.
  66. #START 新增定义####################################################################
  67. definitions:
  68. Person:
  69. required:
  70. - username
  71. properties:
  72. firstName:
  73. type: string
  74. lastName:
  75. type: string
  76. username:
  77. type: string
  78. Persons:
  79. type: array
  80. items:
  81. $ref: "#/definitions/Person"
  82. # END 新增定义####################################################################

文档简化了很多。这得益于OpenAPI规范中关于定义(definition)的章节中允许我们“一处定义,处处使用”。

3.1.1 添加定义 (definitions)项

我们首先在API文档的尾部添加一个定义 (definitions)项(其实它也可以放在文档的任意位置,只不过大家习惯放在文档末尾):


   
   
   
   
  1. 404:
  2. description: The Person does not exists.
  3. #START############################################################################
  4. definitions:
  5. # END ############################################################################

3.1.2 增加一个可重用的(对象)定义

然后我们增加一个 Person 对象的定义:


   
   
   
   
  1. definitions:
  2. #START############################################################################
  3. Person:
  4. required:
  5. - username
  6. properties:
  7. firstName:
  8. type: string
  9. lastName:
  10. type: string
  11. username:
  12. type: string
  13. # END ############################################################################

3.1.3 引用一个定义来增加另一个定义

在定义项中,我们可以立即引用刚才定义好的 Person 来增加另一个定义PersonsPersons 是一个 Person 对象的数组。与之前直接定义的不同之处是,我们增加了一个引用reference)属性,也就是 $ref来引用 Person 。


   
   
   
   
  1. Persons:
  2. type: array
  3. items:
  4. $ref: "#/definitions/Person"

3.1.4 在响应消息中使用定义

一旦定义好了 Person ,我们可以把原来在响应消息中相应的定义字段替换掉。

3.1.4.1 get/persons

原来:


   
   
   
   
  1. responses:
  2. 200:
  3. description: A list of Person
  4. schema:
  5. type: array
  6. items:
  7. required:
  8. - username
  9. properties:
  10. firstName:
  11. type: string
  12. lastName:
  13. type: string

现在:


   
   
   
   
  1. responses:
  2. 200:
  3. description: A list of Person
  4. schema:
  5. $ref: "#/definitions/Persons"

3.1.4.2 get/persons/{username}

原来:


   
   
   
   
  1. responses:
  2. 200:
  3. description: A Person
  4. schema:
  5. required:
  6. - username
  7. properties:
  8. firstName:
  9. type: string
  10. lastName:
  11. type: string
  12. username:
  13. type: string

现在:


   
   
   
   
  1. responses:
  2. 200:
  3. description: A Person
  4. schema:
  5. $ref: "#/definitions/Person"

3.1.5 在参数中使用定义

不仅仅在消息中可以使用定义,在参数中也可以使用。

3.1.5.1 post /persons

原来:


   
   
   
   
  1. post:
  2. summary: Creates a person
  3. description: Adds a new person to the persons list.
  4. parameters:
  5. - name: person
  6. in: body
  7. description: The person to create.
  8. schema:
  9. required:
  10. - username
  11. properties:
  12. firstName:
  13. type: string
  14. lastName:
  15. type: string
  16. username:
  17. type: string

现在:


   
   
   
   
  1. post:
  2. summary: Creates a person
  3. description: Adds a new person to the persons list.
  4. parameters:
  5. - name: person
  6. in: body
  7. description: The person to create.
  8. schema:
  9. $ref: "#/definitions/Person"

3.2 简化响应消息

我们看到了引用 ($ref)的作用,接下来我们再把它用到响应消息的定义中:


   
   
   
   
  1. swagger: "2.0"
  2. info:
  3. version: 1.0 .0
  4. title: Simple API
  5. description: A simple API to learn how to write OpenAPI Specification
  6. schemes:
  7. - https
  8. host: simple.api
  9. basePath: /openapi101
  10. paths:
  11. /persons:
  12. get:
  13. summary: Gets some persons
  14. description: Returns a list containing all persons. The list supports paging.
  15. parameters:
  16. - name: pageSize
  17. in: query
  18. description: Number of persons returned
  19. type: integer
  20. - name: pageNumber
  21. in: query
  22. description: Page number
  23. type: integer
  24. responses:
  25. 200:
  26. description: A list of Person
  27. schema:
  28. $ref: "#/definitions/Persons"
  29. #START############################################################################
  30. 500:
  31. $ref: "#/responses/Standard500ErrorResponse"
  32. # END ############################################################################
  33. post:
  34. summary: Creates a person
  35. description: Adds a new person to the persons list.
  36. parameters:
  37. - name: person
  38. in: body
  39. description: The person to create.
  40. schema:
  41. $ref: "#/definitions/Person"
  42. responses:
  43. 204:
  44. description: Persons succesfully created.
  45. 400:
  46. description: Persons couldn 't have been created.
  47. #START############################################################################
  48. 500:
  49. $ref: "#/responses/Standard500ErrorResponse"
  50. # END ############################################################################
  51. /persons/{username}:
  52. get:
  53. summary: Gets a person
  54. description: Returns a single person for its username.
  55. parameters:
  56. - name: username
  57. in: path
  58. required: true
  59. description: The person 's username
  60. type: string
  61. responses:
  62. 200:
  63. description: A Person
  64. schema:
  65. $ref: "#/definitions/Person"
  66. 404:
  67. description: The Person does not exists.
  68. #START############################################################################
  69. 500:
  70. $ref: "#/responses/Standard500ErrorResponse"
  71. # END ############################################################################
  72. definitions:
  73. Person:
  74. required:
  75. - username
  76. properties:
  77. firstName:
  78. type: string
  79. lastName:
  80. type: string
  81. username:
  82. type: string
  83. Persons:
  84. type: array
  85. items:
  86. $ref: "#/definitions/Person"
  87. #START############################################################################
  88. Error:
  89. properties:
  90. code:
  91. type: string
  92. message:
  93. type: string
  94. responses:
  95. Standard500ErrorResponse:
  96. description: An unexpected error occured.
  97. schema:
  98. $ref: "#/definitions/Error"
  99. # END ############################################################################

3.2.1 定义可重用的HTTP 500 响应

发生HTTP 500错误时,假如我们希望每一个API操作都返回一个带有错误码(error code)和描述信息(message)的响应,我们可以这样做:


   
   
   
   
  1. paths:
  2. /persons:
  3. get:
  4. summary: Gets some persons
  5. description: Returns a list containing all persons. The list supports paging.
  6. parameters:
  7. - name: pageSize
  8. in: query
  9. description: Number of persons returned
  10. type: integer
  11. - name: pageNumber
  12. in: query
  13. description: Page number
  14. type: integer
  15. responses:
  16. 200:
  17. description: A list of Person
  18. schema:
  19. $ref: "#/definitions/Persons"
  20. #START############################################################################
  21. 500:
  22. description: An unexpected error occured.
  23. schema:
  24. properties:
  25. code:
  26. type: string
  27. message:
  28. type: string
  29. # END ############################################################################
  30. post:
  31. summary: Creates a person
  32. description: Adds a new person to the persons list.
  33. parameters:
  34. - name: person
  35. in: body
  36. description: The person to create.
  37. schema:
  38. $ref: "#/definitions/Person"
  39. responses:
  40. 204:
  41. description: Persons succesfully created.
  42. 400:
  43. description: Persons couldn 't have been created.
  44. #START############################################################################
  45. 500:
  46. description: An unexpected error occured.
  47. schema:
  48. properties:
  49. code:
  50. type: string
  51. message:
  52. type: string
  53. # END ############################################################################
  54. /persons/{username}:
  55. get:
  56. summary: Gets a person
  57. description: Returns a single person for its username.
  58. parameters:
  59. - name: username
  60. in: path
  61. required: true
  62. description: The person 's username
  63. type: string
  64. responses:
  65. 200:
  66. description: A Person
  67. schema:
  68. $ref: "#/definitions/Person"
  69. 404:
  70. description: The Person does not exists.
  71. #START############################################################################
  72. 500:
  73. description: An unexpected error occured.
  74. schema:
  75. properties:
  76. code:
  77. type: string
  78. message:
  79. type: string
  80. # END ############################################################################

3.2.2 增加一个Error定义

按照“一处定义、处处引用”的原则,我们可以在定义项中增加 Error 的定义:


   
   
   
   
  1. definitions:
  2. Person:
  3. required:
  4. - username
  5. properties:
  6. firstName:
  7. type: string
  8. lastName:
  9. type: string
  10. username:
  11. type: string
  12. Persons:
  13. type: array
  14. items:
  15. $ref: "#/definitions/Person"
  16. #START############################################################################
  17. Error:
  18. properties:
  19. code:
  20. type: string
  21. message:
  22. type: string
  23. # END ############################################################################

而且我们也学会了使用引用$ref),所以我们可以这样写:


   
   
   
   
  1. paths:
  2. /persons:
  3. get:
  4. summary: Gets some persons
  5. description: Returns a list containing all persons. The list supports paging.
  6. parameters:
  7. - name: pageSize
  8. in: query
  9. description: Number of persons returned
  10. type: integer
  11. - name: pageNumber
  12. in: query
  13. description: Page number
  14. type: integer
  15. responses:
  16. 200:
  17. description: A list of Person
  18. schema:
  19. $ref: "#/definitions/Persons"
  20. 500:
  21. description: An unexpected error occured.
  22. schema:
  23. #START############################################################################
  24. $ref: "#/definitions/Error"
  25. # END ############################################################################
  26. post:
  27. summary: Creates a person
  28. description: Adds a new person to the persons list.
  29. parameters:
  30. - name: person
  31. in: body
  32. description: The person to create.
  33. schema:
  34. $ref: "#/definitions/Person"
  35. responses:
  36. 204:
  37. description: Persons succesfully created.
  38. 400:
  39. description: Persons couldn 't have been created.
  40. 500:
  41. description: An unexpected error occured.
  42. schema:
  43. #START############################################################################
  44. $ref: "#/definitions/Error"
  45. # END ############################################################################
  46. /persons/{username}:
  47. get:
  48. summary: Gets a person
  49. description: Returns a single person for its username.
  50. parameters:
  51. - name: username
  52. in: path
  53. required: true
  54. description: The person 's username
  55. type: string
  56. responses:
  57. 200:
  58. description: A Person
  59. schema:
  60. $ref: "#/definitions/Person"
  61. 404:
  62. description: The Person does not exists.
  63. 500:
  64. description: An unexpected error occured.
  65. schema:
  66. #START############################################################################
  67. $ref: "#/definitions/Error"
  68. # END ############################################################################

3.2.3 定义一个可重用的响应消息

上面的文档中,还是有一些重复的内容。我们可以根据OpenAPI规范中的responses章节的描述,通过定义一个可重用的响应消息,来进一步简化文档。


   
   
   
   
  1. definitions:
  2. Person:
  3. required:
  4. - username
  5. properties:
  6. firstName:
  7. type: string
  8. lastName:
  9. type: string
  10. username:
  11. type: string
  12. Persons:
  13. type: array
  14. items:
  15. $ref: "#/definitions/Person"
  16. Error:
  17. properties:
  18. code:
  19. type: string
  20. message:
  21. type: string
  22. #START############################################################################
  23. responses:
  24. Standard500ErrorResponse:
  25. description: An unexpected error occured.
  26. schema:
  27. $ref: "#/definitions/Error"
  28. # END ############################################################################

注意:响应消息中引用了 Error 的定义。

3.2.4 使用已定义的响应消息

我们还是通过引用$ref)来使用一个已经定义好的响应消息,比如:

3.2.4.1 get /users


   
   
   
   
  1. responses:
  2. 200:
  3. description: A list of Person
  4. schema:
  5. $ref: "#/definitions/Persons"
  6. #START############################################################################
  7. 500:
  8. $ref: "#/responses/Standard500ErrorResponse"
  9. # END ############################################################################

3.2.4.2 post/users


   
   
   
   
  1. responses:
  2. 204:
  3. description: Persons succesfully created.
  4. 400:
  5. description: Persons couldn 't have been created.
  6. #START############################################################################
  7. 500:
  8. $ref: "#/responses/Standard500ErrorResponse"
  9. # END ############################################################################

3.2.4.3 get/users/{username}


   
   
   
   
  1. responses:
  2. 200:
  3. description: A Person
  4. schema:
  5. $ref: "#/definitions/Person"
  6. 404:
  7. description: The Person does not exists.
  8. #START############################################################################
  9. 500:
  10. $ref: "#/responses/Standard500ErrorResponse"
  11. # END ############################################################################

3.3 简化参数定义

类似数据模型、响应消息的简化,参数定义的简化也很容易。


   
   
   
   
  1. swagger: "2.0"
  2. info:
  3. version: 1.0 .0
  4. title: Simple API
  5. description: A simple API to learn how to write OpenAPI Specification
  6. schemes:
  7. - https
  8. host: simple.api
  9. basePath: /openapi101
  10. paths:
  11. /persons:
  12. get:
  13. summary: Gets some persons
  14. description: Returns a list containing all persons. The list supports paging.
  15. #START############################################################################
  16. parameters:
  17. - $ref: "#/parameters/pageSize"
  18. - $ref: "#/parameters/pageNumber"
  19. # END ############################################################################
  20. responses:
  21. 200:
  22. description: A list of Person
  23. schema:
  24. $ref: "#/definitions/Persons"
  25. 500:
  26. $ref: "#/responses/Standard500ErrorResponse"
  27. post:
  28. summary: Creates a person
  29. description: Adds a new person to the persons list.
  30. parameters:
  31. - name: person
  32. in: body
  33. description: The person to create.
  34. schema:

你可能感兴趣的:([架构及设计模式])