OpenAPI 2.0 和OpenApi3.0比较

OpenAPI 2.0 和OpenApi3.0比较

该部分内容取自于OpenAPI spec (swagger) v2 vs v3

多主机

OpenAPI 2.0 允许指定单个主机和基本路径,而schemes 属性允许指定http 和https,因此有效地启用了仅在方案中有所不同的两个主机。在 OpenAPI 3.0)中,新的根级别主机对象包含一组对象,其中包含主机、basePath 和方案属性。

通过将其构造为对象数组,可以支持 API 的任意数量的根 URL,并且它允许方案、主机和 basePath 属性之间更清晰的关联。它还减少了所需的根级别属性的数量,从而简化了文档结构。

此外,主机、基本路径和方案可以在路径项级别被覆盖。这应该可以更轻松地将单独主机上提供的功能合并到 API 描述中。

URL结构

目前,Swagger 2 允许您定义方案、主机和 baseUrl,它们会合并到您的 URL 中。现在,您可以拥有多个 URL,并且可以在任何地方定义它们,这意味着您可以像以前一样在基础上只有一个,或者如果基础 URL 不同,则特定端点可以拥有自己的服务器。

此外,现在允许路径模板。在 OpenAPI 3 中,仅在实际端点 URL 中允许这样做。您可以使用变量属性定义模板。

Swagger 2

info:
  title: Swagger Sample App
host: example.com
basePath: /v1
schemes: ['http', 'https']
OpenAPI 3
servers:
- url: https://{subdomain}.site.com/{version}
  description: The main prod server
  variables:
    subdomain:
      default: production
    version:
      enum:
        - v1
        - v2
      default: v2

路径项目也有一些细微的变化。他们现在可以接受描述。此外,您现在还可以为每个路径指定其自己的基本 URL(例如,http://login.example.com)。

URL verbs

您不再被允许为 GET 和 DELETE 定义请求body。最后,还有对 TRACE 的支持。

组件

Swagger 2 有定义的概念,但它们有些随意并且定义不那么明确。 OpenAPI 3 尝试将概念标准化为组件,这些组件是可以在多个位置重用的可定义对象。

开放 API 规范 3.0 提供了组件对象,其中可以包含:

schemas
parameters
responses
examples
security schemes
links
request bodies
headers
callbacks
This component object won’t affect the API until it is referenced somewhere in the API.

优点:如果一个 API 的多个操作需要类似的输入结构,则可以在组件下将输入结构定义为请求主体,并且可以在多个路径中重用。同样,标头、响应等也可以重用。

"components": {
  "schemas": {
    "Category": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64"
        },
        "name": {
          "type": "string"
        }
      }
    },
    "Tag": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64"
        },
        "name": {
          "type": "string"
        }
      }
    }
  },
  "parameters": {
    "skipParam": {
      "name": "skip",
      "in": "query",
      "description": "number of items to skip",
      "required": true,
      "schema": {
        "type": "integer",
        "format": "int32"
      }
    },
    "limitParam": {
      "name": "limit",
      "in": "query",
      "description": "max records to return",
      "required": true,
      "schema" : {
        "type": "integer",
        "format": "int32"
      }
    }
  },
  "responses": {
    "NotFound": {
      "description": "Entity not found."
    },
    "IllegalInput": {
      "description": "Illegal input for operation."
    },
    "GeneralError": {
      "description": "General Error",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/GeneralError"
          }
        }
      }
    }
  }
}

请求格式

Swagger 2 最令人困惑的方面之一是 body/formData。它们是参数的子集——你只能有一个或另一个——如果你使用 body,格式与其余参数不同。 (你只能有 on body 参数,名称不相关,格式不同等等。)

现在,body 已移至其自己的名为 requestBody 的部分,并且 formData 已合并到其中。

此外,cookies 已被添加为参数类型(除了现有的标头、路径和查询选项之外)。

Swagger 2

"/pets/{petId}":
  post:
    parameters:
    - name: petId
      in: path
      description: ID of pet to update
      required: true
      type: string
    - name: user
      in: body
      description: user to add to the system
      required: true
      schema:
        type: array
        items:
          type: string

OpenAPI 3

"/pets/{petId}":
  post:
    requestBody:
      description: user to add to the system
      required: true
      content:
        application/json: 
          schema:
            type: array
            items:
              $ref: '#/components/schemas/Pet'
          examples:
            - name: Fluffy
              petType: Cat
            - http://example.com/pet.json
    parameters:
      - name: petId
        in: path
        description: ID of pet to update
        required: true
        type: string

新的 requestBody 支持不同的媒体类型(内容是 mimetypes 的数组,例如 application/json 或 text/plain,尽管您可以使用 / 表示支持所有类型)。

对于参数,您有两种定义方式的选择。您可以定义一个模式(如 2.0 中所示),它可以让您描述该项目。或者,如果更复杂,您可以使用 content,这与 requestBody 相同。

Request body content negotiation

3.0 版本提供了支持内容协商的 requestBody,以便您可以为各种媒体类型定义不同的架构和示例。 requestBody 允许 Web 服务接受和返回不同格式的数据,例如图像、纯文本、XML 和 JSON。它还允许您提供一个或多个示例。

案例 (Examples)

requestBody 有很多新功能。您现在可以为 requestBody 提供一个示例(或示例数组)。这非常灵活(您可以传递完整的示例、引用,甚至示例的 URL)。

链接(Linking)

链接是 OpenAPI 3 最有趣的新增功能之一。它有点复杂,但可能非常强大。这基本上是描述“接下来会发生什么”的一种方式。 (对于熟悉的人来说,它与 HATEOAS / 超媒体 API 具有相同的风格。)

假设您有一个用户,它有一个 addressId。这个addressId 本身是没什么用的。您可以使用链接来展示如何“扩展”它,并获取完整的地址。
paths:
/users/{userId}:
get:
responses:
200:
links:
address:
operationId: getAddressWithAddressId
parameters:
addressId: ‘$response.body#/addressId’
看看那里发生了什么?在 /users/{userId} 的响应中,我们返回一个 addressId。这些链接描述了我们如何通过引用 $response.body#/addressId 来获取地址。

另一个用例是分页。如果您获取 100 个结果,链接可以显示如何获取结果 101-200。它很灵活,这意味着它可以处理从限制到光标的任何分页方案。

为此,3.0 草案规范引入了 links 对象,以便描述基于从初始资源检索到的信息可以访问哪些新资源。这不一定是超媒体驱动的,因为新资源的 URL 尚未嵌入到返回的有效负载中,但它们是根据 OpenAPI 规范中定义的规则构建的。引入了新的表达式语法,以允许响应中的信息与链接操作中的参数相关联。

安全(Security)

对安全性进行了一系列更改!它已被重命名,OAuth2 流名称已更新,您可以拥有多个流,并且支持 OpenID Connect。基本类型已重命名为http,现在安全性可以有一个方案和一个bearerFormat。

Swagger 2
securityDefinitions:
UserSecurity:
type: basic
APIKey:
type: apiKey
name: Authorization
in: header
security:

  • UserSecurity: []
  • APIKey: []
    OpenAPI 3
    components:
    securitySchemes:
    UserSecurity:
    type: http
    scheme: basic
    APIKey:
    type: http
    scheme: bearer
    bearerFormat: TOKEN
    security:
  • UserSecurity: []
  • APIKey: []

回调(Callbacks)

Webhook 以发布/订阅模式利用 HTTP,它们已成为 API 提供商(包括 Slack、GitHub 和许多其他流行服务)中的流行模式。 Webhooks 使用简单,并且非常适合现有的基于 HTTP 的 API 风格。然而,对 OpenAPI 规范的一个批评是它无法描述出站 HTTP 请求及其预期响应。新的回调对象使这成为可能。回调对象可以附加到订阅操作,以描述订阅者可能期望的出站操作。

JSON Schema

许多请求都要求扩展 OpenAPI 规范允许包含的 JSON 模式的更复杂功能的 JSON 模式子集。在 2.0 规范流程中,代码生成的潜在工具复杂性促使排除 anyOf 和 oneOf。然而,许多用户要求放宽该限制,即使这会损害对这些功能的工具支持。这是规范设计中的巨大挑战之一,在做出这样的选择时,要知道是为人们提供可能会割伤自己的锋利工具,还是依靠经验来拒绝负担,这两者之间的关系是否更好?这个责任太大了。虽然OpenAPI 2.0采取了更为保守的方法,但用户群的经验已经变得更加丰富,因此一些限制正在取消,用户将不得不做出明智的选择。

Type 可以是数组

在 OpenAPI 的早期版本中,类型只能是单个字符串。但在 JSON Schema 中,类型可以是字符串数组。在 2.0 版本中没有解决此问题的方法,但在 3.0 版本中,您可以使用 oneOf 选择多种类型:
oneOf:

  • type: string
  • type: integer
    With OpenAPI 3.1, the specification now supports type as an array:
    type: [string, integer]

Type 不支持 null类型

OpenAPI 2.0 和 3.0 都不支持 null 作为类型,但 JSON Schema 确实支持 null 类型。 OpenAPI 3.0 包含字段名称 nullable,如果您希望值为 null,可以将其设置为 true:
type: string
nullable: true
不过,3.1 版本中添加了对 null 类型的支持,并且删除了 nullable 类型。
type: [string, “null”]

升级Swagger

依赖

替换依赖

旧依赖

<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger2</artifactId>
   <version>2.9.2</version>
</dependency>
<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger-ui</artifactId>
   <version>2.9.2</version>
</dependency>

替换为新依赖:

<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-boot-starter</artifactId>
  <version>3.0.0</version>
</dependency>

修改配置

  1. 移除注解@EnableSwagger2(普通springmvc项目还需加上@EnableOpenApi)
  2. 文档类型改为OAS_30
@Configuration
public class SwaggerConfig {
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.OAS_30) // v2 不同
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.example.swaggerv3.controller"))
                .build();
    }
}