OpenAPI V3 Spec校验工具

项目结构

  • oas-validator-core,核心API及骨架实现
  • oas-validator-core-spring,骨架的Spring Boot Starter
  • oas-validator-test,核心API的测试帮助类
  • oas-validator-compliance,合规性校验实现
  • oas-validator-compliance-spring,合规性校验的Spring Boot Starter
  • oas-validator-compatibility,兼容性校验实现
  • oas-validator-compatibility-spring,兼容性校验实现的Spring Boot Starter
  • oas-validator-web,校验工具的操作UI

合规性校验

OAS必须符合OAS 3.0.2规范(比如属性的名称、REQUIED要求)。除此之外则是我们自己的定义的合规性检查。

一些字符串匹配规则

  • Lower Camel Case:首字母小写的驼峰,对应的正则^[a-z]+((\d)|([A-Z0-9][a-z0-9]+))*([A-Z])?$
  • Upper Camel Case:首字母大写的驼峰,对应的正则^[A-Z]([a-z0-9]+[A-Z]?)*$
  • Upper Hyphen Case:单词首字母大写,多个单词用-连接,比如Content-TypeAcceptX-Rate-Limit-Limit。对应的正则:^([A-Z][a-z0-9]*-)*([A-Z][a-z0-9]*)$

OpenAPI Object doc

Info Object doc

  • description属性,必须填写

Tag Object doc

Paths Object doc

Path Item Object doc

Operation Object doc

Parameter Object doc

Request Body Object doc

Media Type Object doc

Responses Object doc

Response Object doc

Schema Object doc

Encoding Object doc

Header Object doc

Components Object doc

兼容性检查

对新旧两个版本的OAS做兼容性检查。

OAS可以使用Reference Object来描述Spec,两个不同的OAS会出现描述不同但语义相同的情况。比如下面的旧OAS没有使用Reference Object,而新OAS则使用了的情况:

旧OAS

openapi: "3.0.0"
info:
  version: 1.0.0
  title: Swagger Petstore
  license:
    name: MIT
servers:
  - url: http://petstore.swagger.io/v1
paths:
  /pets:
    post:
      summary: List all pets
      operationId: listPets
      requestBody:
        content:
          application/json:
            schema:
              type: array
              items:
                type: object
                properties:
                  Foo:
                    type: string
      responses:
        '200':
          description: A paged array of pets

新OAS

paths:
  /pets:
    post:
      operationId: listPets
      requestBody:
        content:
          application/json: 
            schema:
              $ref: '#/components/schemas/Foo'
      responses:
        '200':
          description: A paged array of pets
components:
  schemas:
    Foo:
      type: array
      items:
        type: object
        properties:
          Foo:
            type: string

因此在检查兼容性的时候会将新旧OAS的Reference Object做解析,然后再检查,下面是一段swagger-parser的例子:

OpenAPIV3Parser parser = new OpenAPIV3Parser();

ParseOptions parseOptions = new ParseOptions();
parseOptions.setResolve(true);
parseOptions.setResolveCombinators(true);
parseOptions.setResolveFully(true);
parseOptions.setFlatten(false);

SwaggerParseResult parseResult = parser.readContents(content, null, parseOptions);

因此,检查下来如果发现不兼容,那么所报告的位置会和原文档有所不同。

Paths Object doc

  • 新OAS必须包含旧OAS的所有的path,如果path使用了Path Templating,只要变量名发生了变化,那么即使语义上相同也会被认为不同,比如/pets/{foo}/pets/{bar}会被认定为不同。

Path Item Object doc

Operation Object doc

Parameter Object doc

  • required属性,只允许true(旧) -> false(新)
  • allowEmptyValue属性,只允许false(旧) -> true(新)的变化
  • style属性,新旧OAS必须保持一致
  • explode属性,新旧OAS必须保持一致
  • allowReserved属性,只允许false(旧) -> true(新)的变化
  • schema属性,见Schema Object兼容性检查
  • content属性,新OAS必须包含旧OAS的所有media type(content的key),且不能新增media type

Request Body Object doc

  • content属性,新OAS必须包含旧OAS的所有media type(content的key)
  • required属性,只允许true(旧) -> false(新)的变化

Media Type Object doc

Responses Object doc

  • default属性,如果旧OAS没有定义default,那么新OAS也不能定义default
  • {Http Status Code}属性,新OAS不允许新增。
  • Response Object兼容性检查

Response Object doc

Schema Object doc

OAS中定义,Schema Object可以直接或间接用在:

不同用途的兼容性检查规则有所不同。

用做请求时

原则上,当Schema Object用在请求时,只允许从紧到松的变化。

  • type, format组合所允许的变化范围
旧(type,format) 新(type,format)
integer, null integer, int64
number, double
number, null
integer, int32 integer, int64
integer, null
number, float
number, double
number, null
integer, int64 integer, null
number, double
number, null
number, null number, double
number, float number, null
number, double
number, double number, null
string, null string, password
string, password string, null
  • allOfoneOfanyOf属性,在combine之后再做检查
  • multipleOf属性,如果旧OAS为null。新OAS必须==旧OAS或者新OAS是旧OAS的因子,比如6(旧)->3(新)
  • maximummaxLengthmaxItemsmaxProperties,如果旧OAS为null,那么新OAS也必须是null。其他情况,新OAS必须>=旧OAS。
  • minimumminLenghtminItemsminProperties,如果旧OAS为null,那么新OAS也必须是null。其他情况,新OAS必须<=旧OAS。
  • exclusiveMaximumexclusiveMinimum属性,仅允许true(旧)->false(新)的变化
  • uniqueItems属性,只允许true(旧)->false(新)的变化。
  • required属性,新OAS必须==旧OAS,或者新OAS是旧OAS的子集。
  • enum属性,新OAS必须==旧OAS,或者新OAS是旧OAS的超集。
  • properties属性,新OAS可以新增property name(properties的key)或者减少property name。
  • nullable属性,只允许false(旧)->true(新)的变化。
  • discriminator属性,新旧OAS必须完全一致。
  • xml属性,新旧OAS必须完全一致。
  • readOnlywriteOnly,新旧OAS必须完全一致。

用做响应时

原则上,当Schema Object用在响应时,只允许从松到紧的变化。

  • type, format组合所允许的变化范围
旧(type,format) 新(type,format)
integer, null integer, int64
integer, int32
integer, int64 integer, null
interger, int32
number, null number, double
number, float
number, double number, null
number, float
string, null string, password
string, password string, null
  • allOfoneOfanyOf属性,在combine之后再做检查
  • multipleOf属性,如果旧OAS为null。新OAS必须==旧OAS或者新OAS是旧OAS的倍数,比如3(旧)->6(新)
  • maximummaxLengthmaxItemsmaxProperties,如果旧OAS为null,那么新OAS也必须是null。其他情况,新OAS必须<=旧OAS。
  • minimumminLenghtminItemsminProperties,如果旧OAS为null,那么新OAS也必须是null。其他情况,新OAS必须>=旧OAS。
  • exclusiveMaximumexclusiveMinimum属性,仅允许false(旧)->true(新)的变化
  • uniqueItems属性,只允许false(旧)->true(新)的变化。
  • required属性,新OAS必须==旧OAS或者,新OAS是旧OAS的超集。
  • enum属性,新OAS必须==旧OAS,或者新OAS是旧OAS的子集。
  • properties属性,新OAS可以新增property name(properties的key)或者减少property name。
  • nullable属性,只允许true(旧)->false(新)的变化。
  • discriminator属性,新旧OAS必须完全一致。
  • xml属性,新旧OAS必须完全一致。
  • readOnlywriteOnly,新旧OAS必须完全一致。

Encoding Object doc

PS. Encoding Object仅针对Request Body Object有用

  • contentType属性,新旧OAS必须保持一致
  • headers属性,新OAS不能新增旧OAS的header name(headers的key),但是可以删除header name
  • style属性,新旧OAS必须保持一致
  • explode属性,新旧OAS必须保持一致
  • allowReserved属性,只允许false(旧) -> true(新)的变化

Header Object doc

Components Object doc

Components Object定义的都是可复用OAS Object,而在检查兼容性的时候所有$ref都已被解析了,因此不需要对Components Object的属性做兼容性检查。