OAS Validator | English
OpenAPI V3 Spec校验工具。
- oas-validator-core,核心API及骨架实现
- oas-validator-core-spring,骨架的Spring Boot Starter
- oas-validator-test,核心API的测试帮助类
- oas-validator-style,风格校验实现
- 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-Type
、Accept
、X-Rate-Limit-Limit
。对应的正则:^([A-Z][a-z0-9]*-)*([A-Z][a-z0-9]*)$
下面是配置文件的例子style-check-rule.properties
:
#######################
# OpenAPI Object
#######################
# openapi property must be 3.0.x and >= 3.0.2
openAPI.openapi.gte=3.0.2
# tags property size should >= 1
openAPI.tags.size.gte=1
# security property size must == 0
openAPI.security.size.eq=0
#######################
# Info Object
#######################
# description property is required
info.description.required=true
#######################
# Tag Object
#######################
# name property, must be upper-camel-case
tag.name.case=upper-camel-case
# tag should be referenced by at least one Operation Object
tag.name.must_be_referenced=true
# description property, required
tag.description.required=true
#######################
# Paths Object
#######################
# path must be lower-camel-case, including Path Templating variable
paths.key.case=lower-camel-case
#######################
# Operation Object
#######################
# summary property, required
operation.summary.required=true
# operationId property, must be lower-camel-case
operation.operationId.case=lower-camel-case
# tags property, size must == 1
operation.tags.size.eq=1
# all tags should references which are defined in $.tags
operation.tags.element.must_reference_root_tags=true
# servers property, size must == 0
operations.servers.size.eq=0
#######################
# Parameter Object
#######################
# description property, required
parameter.description.required=true
# name property, for header parameter, must be upper-hyphen-case
parameter.name.header.case=upper-hyphen-case
# name property, for cookie parameter, must be lower-camel-case
parameter.name.cookie.case=lower-camel-case
# name property, for path parameter, must be lower-camel-case
parameter.name.path.case=lower-camel-case
# name property, for query parameter, must be lower-camel-case
parameter.name.query.case=lower-camel-case
#######################
# RequestBody Object
#######################
# description property, required
requestBody.description.required=true
#######################
# Response Object
#######################
# headers property's key must be upper-hyphen-case
response.headers.key.case=upper-hyphen-case
#######################
# Schema Object
#######################
# title property, required if parent is Schema Object or Components Object
schema.title.required=true
# properties property, name(properties key) must be lower-camel-case
schema.properties.key.case=lower-camel-case
#######################
# Encoding Object
#######################
# headers property's key must be upper-hyphen-case
encoding.headers.key.case=upper-hyphen-case
#######################
# Header Object
#######################
# description property, required
header.description.required=true
#######################
# Components Object
#######################
# schemas property's key must be upper-camel-case
components.schemas.key.case=upper-camel-case
# responses property's key must be upper-camel-case
components.responses.key.case=upper-camel-case
# parameters property's key must be upper-camel-case
components.parameters.key.case=upper-camel-case
# examples property's key must be upper-camel-case
components.examples.key.case=upper-camel-case
# requestBodies property's key must be upper-camel-case
components.requestBodies.key.case=upper-camel-case
# headers property's key must be upper-hyphen-case
components.headers.key.case=upper-hyphen-case
# links property's key must be upper-camel-case
components.links.key.case=upper-hyphen-case
# callbacks property's key must be upper-camel-case
components.callbacks.key.case=upper-camel-case
# headers property's key must be upper-camel-case
components.headers.key.case=upper-camel-case
对新旧两个版本的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
- 新OAS必须包含旧OAS的所有的get/put/post/delete/...Operation Object
Operation Object doc
operationId
属性,新旧OAS必须完全一致。parameters
属性,对它检查须在考虑到Path Item Object parameters属性的情况下进行:- 新OAS可以新增Parameter Object,但是新增的Parameter Object的
required
属性必须为false
- 新OAS可以删除Parameter Object
- 针对单个Parameter Object的修改的检查见Parameter Object兼容性检查(在同一个Operation Object下Parameter Object依靠
name
和in
两个属性作为ID)。
- 新OAS可以新增Parameter Object,但是新增的Parameter Object的
requestBody
属性,见Request Body Object兼容性检查responses
属性,见Responses Object兼容性检查
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
schema
属性,见Schema Object兼容性检查encoding
属性,该属性仅适用于requestBody
,因此新旧OAS的property name(encoding
的key)必须完全一致
Responses Object doc
default
属性,如果旧OAS没有定义default
,那么新OAS也不能定义default
。{Http Status Code}
属性,新OAS不允许新增。- 见Response Object兼容性检查
Response Object doc
headers
属性,新OAS必须包含旧OAS的所有header name(headers
的key),可以新增header namecontent
属性,新OAS必须包含旧OAS的所有media type(content
的key),可以新增media type
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 |
allOf
、oneOf
、anyOf
属性,在combine之后再做检查multipleOf
属性,如果旧OAS为null。新OAS必须==旧OAS或者新OAS是旧OAS的因子,比如6(旧)->3(新)maximum
、maxLength
、maxItems
、maxProperties
,如果旧OAS为null,那么新OAS也必须是null。其他情况,新OAS必须>=旧OAS。minimum
、minLenght
、minItems
、minProperties
,如果旧OAS为null,那么新OAS也必须是null。其他情况,新OAS必须<=旧OAS。exclusiveMaximum
、exclusiveMinimum
属性,仅允许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必须完全一致。readOnly
、writeOnly
,新旧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 |
allOf
、oneOf
、anyOf
属性,在combine之后再做检查multipleOf
属性,如果旧OAS为null。新OAS必须==旧OAS或者新OAS是旧OAS的倍数,比如3(旧)->6(新)maximum
、maxLength
、maxItems
、maxProperties
,如果旧OAS为null,那么新OAS也必须是null。其他情况,新OAS必须<=旧OAS。minimum
、minLenght
、minItems
、minProperties
,如果旧OAS为null,那么新OAS也必须是null。其他情况,新OAS必须>=旧OAS。exclusiveMaximum
、exclusiveMinimum
属性,仅允许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必须完全一致。readOnly
、writeOnly
,新旧OAS必须完全一致。
Encoding Object doc
PS. Encoding Object仅针对Request Body Object有用
contentType
属性,新旧OAS必须保持一致headers
属性,新OAS不能新增旧OAS的header name(headers
的key),但是可以删除header namestyle
属性,新旧OAS必须保持一致explode
属性,新旧OAS必须保持一致allowReserved
属性,只允许false(旧) -> true(新)
的变化
Header Object doc
schema
属性,见Schema Object兼容性检查
Components Object doc
Components Object定义的都是可复用OAS Object,而在检查兼容性的时候所有$ref
都已被解析了,因此不需要对Components Object的属性做兼容性检查。