定义

版本 3.0.0

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 RFC2119 RFC8174 when, and only when, they appear in all capitals, as shown here.

This document is licensed under The Apache License, Version 2.0.

介绍

OpenAPI 规范(OAS),是定义一个标准的、与具体编程语言无关的RESTful API的规范。OpenAPI 规范使得人类和计算机都能在“不接触任何程序源代码和文档、不监控网络通信”的情况下理解一个服务的作用。如果您在定义您的 API 时做的很好,那么使用 API 的人就能非常轻松地理解您提供的 API 并与之交互了。

如果您遵循 OpenAPI 规范来定义您的 API,那么您就可以用文档生成工具来展示您的 API,用代码生成工具来自动生成各种编程语言的服务器端和客户端的代码,用自动测试工具进行测试等等。

目录

术语定义

开放API文档

一(或多)份用来定义或描述一个API的文档。

路径模板

路径模板指用大括号标记来标记一段URL作为可替换的路径参数。

媒体类型

媒体类型定义分散于多处。 媒体类型定义应当符合RFC6838

以下是一些媒体类型定义的示例:

  text/plain; charset=utf-8
  application/json
  application/vnd.github+json
  application/vnd.github.v3+json
  application/vnd.github.v3.raw+json
  application/vnd.github.v3.text+json
  application/vnd.github.v3.html+json
  application/vnd.github.v3.full+json
  application/vnd.github.v3.diff
  application/vnd.github.v3.patch

HTTP状态码

HTTP状态码被用来表示一次请求的被执行状态。 RFC7231定义了有效的状态码,可以在IANA Status Code Registry找到已经被注册的状态码的列表。

规范

版本

开放API规范使用符合语义化版本 2.0.0(semver)规范的版本号。

语义化版本的主版本号次版本号部分(比如3.0)应当被用来标记开放API规范的特性变动。通常 .修订号 版本被用来表示本文档文档的错误修正而不是特性变动。支持开放API规范3.0的工具应该兼容所有3.0.*的版本,工具不应当关注修订版本号,比如3.0.03.0.1对它来说应该没有任何区别。

此后开放API规范的相同主版本号下更高次要版本的发布不应当对面向低于此次要版本号开发的工具的造成干扰。因此3.1.0版本的规范应当可以在面向3.0.0版本规范开发的工具内使用。

任何兼容开放API规范 3.*.* 的文档应当包含一个openapi 字段用来表明它使用的规范的语义化版本。

格式

一份遵从开放API规范的文档是一个自包含的JSON对象,可以使用JSON或YAML格式编写。

比如一个字段有一组值,用JSON格式表示为:

{
   "field": [ 1, 2, 3 ]
}

规范内的所有字段名都是小写

字段分为两种:固定字段和模式字段。固定字段的字段名是确定的,模式字段的字段名需要符合一定的模式。

如果一个对象里有模式字段,那么在这个对象里的模式字段的名字不能有重复的。

为了保留在 YAML 和 JSON 格式之间转换的能力,推荐使用1.2版本的YAML格式,而且还需要符合以下限制:

注意: 虽然API文档是使用 YAML 或 JSON 格式书写的,但是API的请求体和响应体或者其他内容可以是任何格式。

文档结构

一份 OpenAPI 文档可以是单个文件也可以被拆分为多个文件, 连接的部分由用户自行决定。在后一种情形下,必须如 JSON Schema 中定义的那样使用 $ref 字段来相互引用。

推荐将根开放API文档命名为openapi.jsonopenapi.yaml

数据类型

在 OAS 中的原始数据类型是基于 JSON Schema Specification Wright Draft 00 所支持的类型。注意 integer 也作为一个被支持的类型并被定义为不包含小数或指数部分的 JSON 数字。 null 不是一个被支持的类型 (查看 nullable 来获得替代解决方案)。 Models 使用 Schema Object 定义,这是一个 JSON Schema Specification Wright Draft 00 的扩展。

原始类型可以有一个可选的修饰属性:format。 OAS 使用多个已知的格式来丰富类型定义。尽管如此,为了文档的需要,format 属性被设计为一个 string 类型的开放属性值,可以包含任意值。比如 "email", "uuid" 等未被此规范定义的格式也可以被使用。没有被定义的 format 属性类型遵从 JSON Schema 中的类型定义。无法识别某个 format 值的工具应该回退到 type 值,就像 format 未被指定一样。

被 OAS 定义的格式:

富文本格式

整个规范中的 description 字段被标记为支持 CommonMark markdown 格式。 OpenAPI 相关的工具在支持 CommonMark 0.27 中描述的富文本格式方面至少需要支持渲染 markerdown。相关工具为了安全考虑可以选择忽略某些 CommonMark 特性。

URL的相对引用

除非明确指定,所有 URL 类型的属性值都可以是相对地址,就如 RFC3986 中定义的那样以 Server Object 作为 Base URI。

$ref 中的相对引用以 JSON Reference 为依据,以当前文档的 URL 作为 base URI. 同时参考 Reference Object

结构

在接下来的叙述中,如果一个字段没有被明确的标记为 必选 或者被描述为 必须应当,那么可以认为它是一个 可选 字段

OpenAPI 对象

这是OpenAPI document的根文档对象。

固定字段

Info 对象

这个对象提供API的元数据。如果客户端需要时可能会用到这些元数据,而且可能会被呈现在编辑工具或者文档生成工具中。

固定字段

Info 对象示例

{
  "title": "Sample Pet Store App",
  "description": "This is a sample server for a pet store.",
  "termsOfService": "http://example.com/terms/",
  "contact": {
    "name": "API Support",
    "url": "http://www.example.com/support",
    "email": "support@example.com"
  },
  "license": {
    "name": "Apache 2.0",
    "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
  },
  "version": "1.0.1"
}
title: Sample Pet Store App
description: This is a sample server for a pet store.
termsOfService: http://example.com/terms/
contact:
  name: API Support
  url: http://www.example.com/support
  email: support@example.com
license:
  name: Apache 2.0
  url: http://www.apache.org/licenses/LICENSE-2.0.html
version: 1.0.1

Contact 对象

所公开的API的联系人信息

固定字段

这个对象可能会被规范扩展扩展。

Contact 对象示例

{
  "name": "API Support",
  "url": "http://www.example.com/support",
  "email": "support@example.com"
}
name: API Support
url: http://www.example.com/support
email: support@example.com

License 对象

公开API的证书信息。

固定字段

这个对象可能会被规范扩展扩展。

License 对象示例

{
  "name": "Apache 2.0",
  "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
}
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html

Server 对象

表示一个服务器的对象。

固定字段

这个对象可能会被规范扩展扩展。

Server 对象示例

单个服务器可以这样描述:

{
  "url": "https://development.gigantic-server.com/v1",
  "description": "Development server"
}
url: https://development.gigantic-server.com/v1
description: Development server

以下内容表示的是有多个服务器时应该如何描述,比如OpenAPI 对象的servers

{
  "servers": [
    {
      "url": "https://development.gigantic-server.com/v1",
      "description": "Development server"
    },
    {
      "url": "https://staging.gigantic-server.com/v1",
      "description": "Staging server"
    },
    {
      "url": "https://api.gigantic-server.com/v1",
      "description": "Production server"
    }
  ]
}
servers:
- url: https://development.gigantic-server.com/v1
  description: Development server
- url: https://staging.gigantic-server.com/v1
  description: Staging server
- url: https://api.gigantic-server.com/v1
  description: Production server

以下内容展示了如何使用变量来配置服务器:

{
  "servers": [
    {
      "url": "https://{username}.gigantic-server.com:{port}/{basePath}",
      "description": "The production API server",
      "variables": {
        "username": {
          "default": "demo",
          "description": "this value is assigned by the service provider, in this example `gigantic-server.com`"
        },
        "port": {
          "enum": [
            "8443",
            "443"
          ],
          "default": "8443"
        },
        "basePath": {
          "default": "v2"
        }
      }
    }
  ]
}
servers:
- url: https://{username}.gigantic-server.com:{port}/{basePath}
  description: The production API server
  variables:
    username:
      # note! no enum here means it is an open value
      default: demo
      description: this value is assigned by the service provider, in this example `gigantic-server.com`
    port:
      enum:
        - '8443'
        - '443'
      default: '8443'
    basePath:
      # open meaning there is the opportunity to use special base paths as assigned by the provider, default is `v2`
      default: v2

Server Variable 对象

表示可用于服务器URL地址模板变量替换的对象。

固定字段

这个对象可能会被规范扩展扩展。

Components 对象

包含开放API规范固定的各种可重用组件。当没有被其他对象引用时,在这里定义定义的组件不会产生任何效果。

固定字段

这个对象可能会被 规范扩展 扩展。

上面定义的所有固定字段的值都是对象,对象包含的key的命名必须满足正则表达式: ^[a-zA-Z0-9\.\-_]+$

字段名示例:

User
User_1
User_Name
user-name
my.org.User

Components 对象示例

"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"
          }
        }
      }
    }
  },
  "securitySchemes": {
    "api_key": {
      "type": "apiKey",
      "name": "api_key",
      "in": "header"
    },
    "petstore_auth": {
      "type": "oauth2",
      "flows": {
        "implicit": {
          "authorizationUrl": "http://example.org/api/oauth/dialog",
          "scopes": {
            "write:pets": "modify pets in your account",
            "read:pets": "read your pets"
          }
        }
      }
    }
  }
}
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'
  securitySchemes:
    api_key:
      type: apiKey
      name: api_key
      in: header
    petstore_auth:
      type: oauth2
      flows:
        implicit:
          authorizationUrl: http://example.org/api/oauth/dialog
          scopes:
            write:pets: modify pets in your account
            read:pets: read your pets

Paths 对象

定义各个的端点和操作的相对路径。这里指定的路径会和 Server 对象 内指定的URL地址组成完整的URL地址,路径可以为空,这依赖于 ACL constraints 的设置。

模式字段

这个对象可能会被规范扩展扩展。

路径模板匹配

假设有以下路径,明确定义的路径 /pets/mine 会被优先匹配:

  /pets/{petId}
  /pets/mine

以下路径被认为是等价的而且是无效的:

  /pets/{petId}
  /pets/{name}

以下路径会产生歧义:

  /{entity}/me
  /books/{id}

Paths 对象示例

{
  "/pets": {
    "get": {
      "description": "Returns all pets from the system that the user has access to",
      "responses": {
        "200": {
          "description": "A list of pets.",
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/pet"
                }
              }
            }
          }
        }
      }
    }
  }
}
/pets:
  get:
    description: Returns all pets from the system that the user has access to
    responses:
      '200':
        description: A list of pets.
        content:
          application/json:
            schema:
              type: array
              items:
                $ref: '#/components/schemas/pet'

Path Item 对象

描述对一个路径可执行的有效操作。依赖与 ACL constraints 的设置,一个Path Item可以是一个空对象,文档的读者仍然可以看到这个路径,但是他们将无法了解到对这个路径可用的任何操作和参数。

固定字段

这个对象可能会被规范扩展扩展。

Path Item 对象示例

{
  "get": {
    "description": "Returns pets based on ID",
    "summary": "Find pets by ID",
    "operationId": "getPetsById",
    "responses": {
      "200": {
        "description": "pet response",
        "content": {
          "*/*": {
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/components/schemas/Pet"
              }
            }
          }
        }
      },
      "default": {
        "description": "error payload",
        "content": {
          "text/html": {
            "schema": {
              "$ref": "#/components/schemas/ErrorModel"
            }
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "description": "ID of pet to use",
      "required": true,
      "schema": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "style": "simple"
    }
  ]
}
get:
  description: Returns pets based on ID
  summary: Find pets by ID
  operationId: getPetsById
  responses:
    '200':
      description: pet response
      content:
        '*/*' :
          schema:
            type: array
            items:
              $ref: '#/components/schemas/Pet'
    default:
      description: error payload
      content:
        'text/html':
          schema:
            $ref: '#/components/schemas/ErrorModel'
parameters:
- name: id
  in: path
  description: ID of pet to use
  required: true
  schema:
    type: array
    style: simple
    items:
      type: string

Operation Object

描述对路径的某个操作。

固定字段

这个对象可能会被规范扩展扩展。

Operation 对象示例

{
  "tags": [
    "pet"
  ],
  "summary": "Updates a pet in the store with form data",
  "operationId": "updatePetWithForm",
  "parameters": [
    {
      "name": "petId",
      "in": "path",
      "description": "ID of pet that needs to be updated",
      "required": true,
      "schema": {
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/x-www-form-urlencoded": {
        "schema": {
          "type": "object",
           "properties": {
              "name": {
                "description": "Updated name of the pet",
                "type": "string"
              },
              "status": {
                "description": "Updated status of the pet",
                "type": "string"
             }
           },
        "required": ["status"]
        }
      }
    }
  },
  "responses": {
    "200": {
      "description": "Pet updated.",
      "content": {
        "application/json": {},
        "application/xml": {}
      }
    },
    "405": {
      "description": "Invalid input",
      "content": {
        "application/json": {},
        "application/xml": {}
      }
    }
  },
  "security": [
    {
      "petstore_auth": [
        "write:pets",
        "read:pets"
      ]
    }
  ]
}
tags:
- pet
summary: Updates a pet in the store with form data
operationId: updatePetWithForm
parameters:
- name: petId
  in: path
  description: ID of pet that needs to be updated
  required: true
  schema:
    type: string
requestBody:
  content:
    'application/x-www-form-urlencoded':
      schema:
       properties:
          name:
            description: Updated name of the pet
            type: string
          status:
            description: Updated status of the pet
            type: string
       required:
         - status
responses:
  '200':
    description: Pet updated.
    content:
      'application/json': {}
      'application/xml': {}
  '405':
    description: Invalid input
    content:
      'application/json': {}
      'application/xml': {}
security:
- petstore_auth:
  - write:pets
  - read:pets

External Documentation 对象

允许引用外部资源来扩展文档。

固定字段

这个对象可能会被规范扩展扩展。

External Documentation 对象示例

{
  "description": "Find more info here",
  "url": "https://example.com"
}
description: Find more info here
url: https://example.com

Parameter Object

描述一个操作参数。

一个参数的唯一性由 namelocation 的组合来确定。

参数位置

有4种可能的参数位置值可用于in字段:

  • path - 与 Path Templating 一起使用,当参数的值是URL操作路径的一部分时可以使用,但是不包含主机地址或基础路径。比如在路径 /items/{itemId} 中,路径参数是 itemId

  • query - 追加在URL地址之后的参数,比如 /items?id=### 中,查询参数是 id

  • header - 请求中使用的自定义请求头,注意在 RFC7230 中规定,请求头的命名是不区分大小写的。

  • cookie - 用于传递特定的cookie值。

固定字段

序列化参数的规则有两种。 对于简单的场景, schemastyle 可以用于描述参数的结构和语法。

对于更复杂的场景,content属性可以定义参数的媒体类型和概要。一个参数必须且只能包含schemacontent属性中的一个。当exampleexamples字段提供了schema对象时,示例必须遵照参数的序列化策略。

样式值

已经定义好了一组style类型用于支持常见的通用的简单参数序列化。

Style 示例

建设一个参数名为color包含如下之一的值:

   string -> "blue"
   array -> ["blue","black","brown"]
   object -> { "R": 100, "G": 200, "B": 150 }

下面这个表展示了各个不同类型值之间的例子。

这个对象可能会被规范扩展扩展。

Parameter 对象示例

一个值数组,数组元素为64位整数值的请求头参数:

{
  "name": "token",
  "in": "header",
  "description": "token to be passed as a header",
  "required": true,
  "schema": {
    "type": "array",
    "items": {
      "type": "integer",
      "format": "int64"
    }
  },
  "style": "simple"
}
name: token
in: header
description: token to be passed as a header
required: true
schema:
  type: array
  items:
    type: integer
    format: int64
style: simple

一个值类型为字符串的路径参数:

{
  "name": "username",
  "in": "path",
  "description": "username to fetch",
  "required": true,
  "schema": {
    "type": "string"
  }
}
name: username
in: path
description: username to fetch
required: true
schema:
  type: string

一个值类型为字符串的可选查询参数,允许通过通过重复参数来传递多个值:

{
  "name": "id",
  "in": "query",
  "description": "ID of the object to fetch",
  "required": false,
  "schema": {
    "type": "array",
    "items": {
      "type": "string"
    }
  },
  "style": "form",
  "explode": true
}
name: id
in: query
description: ID of the object to fetch
required: false
schema:
  type: array
  items:
    type: string
style: form
explode: true

一个任意格式的查询参数,允许使用指定类型的未定义参数:

{
  "in": "query",
  "name": "freeForm",
  "schema": {
    "type": "object",
    "additionalProperties": {
      "type": "integer"
    },
  },
  "style": "form"
}
in: query
name: freeForm
schema:
  type: object
  additionalProperties:
    type: integer
style: form

使用content定义序列化方法的复杂参数:

{
  "in": "query",
  "name": "coordinates",
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "required": [
          "lat",
          "long"
        ],
        "properties": {
          "lat": {
            "type": "number"
          },
          "long": {
            "type": "number"
          }
        }
      }
    }
  }
}
in: query
name: coordinates
content:
  application/json:
    schema:
      type: object
      required:
        - lat
        - long
      properties:
        lat:
          type: number
        long:
          type: number

Request Body Object

定义请求体。

固定字段

这个对象可能会被规范扩展扩展。

Request Body 示例

一个引用了模型定义的请求体。

{
  "description": "user to add to the system",
  "content": {
    "application/json": {
      "schema": {
        "$ref": "#/components/schemas/User"
      },
      "examples": {
          "user" : {
            "summary": "User Example",
            "externalValue": "http://foo.bar/examples/user-example.json"
          }
        }
    },
    "application/xml": {
      "schema": {
        "$ref": "#/components/schemas/User"
      },
      "examples": {
          "user" : {
            "summary": "User example in XML",
            "externalValue": "http://foo.bar/examples/user-example.xml"
          }
        }
    },
    "text/plain": {
      "examples": {
        "user" : {
            "summary": "User example in Plain text",
            "externalValue": "http://foo.bar/examples/user-example.txt"
        }
      }
    },
    "*/*": {
      "examples": {
        "user" : {
            "summary": "User example in other format",
            "externalValue": "http://foo.bar/examples/user-example.whatever"
        }
      }
    }
  }
}
description: user to add to the system
content:
  'application/json':
    schema:
      $ref: '#/components/schemas/User'
    examples:
      user:
        summary: User Example
        externalValue: 'http://foo.bar/examples/user-example.json'
  'application/xml':
    schema:
      $ref: '#/components/schemas/User'
    examples:
      user:
        summary: User Example in XML
        externalValue: 'http://foo.bar/examples/user-example.xml'
  'text/plain':
    examples:
      user:
        summary: User example in text plain format
        externalValue: 'http://foo.bar/examples/user-example.txt'
  '*/*':
    examples:
      user:
        summary: User example in other format
        externalValue: 'http://foo.bar/examples/user-example.whatever'

请求体是一个字符串的数组:

{
  "description": "user to add to the system",
  "content": {
    "text/plain": {
      "schema": {
        "type": "array",
        "items": {
          "type": "string"
        }
      }
    }
  }
}
description: user to add to the system
required: true
content:
  text/plain:
    schema:
      type: array
      items:
        type: string

Media Type 对象

每种媒体类型对象都有相应的结构和示例来描述它。

固定字段

这个对象可能会被规范扩展扩展。

Media Type 示例

{
  "application/json": {
    "schema": {
         "$ref": "#/components/schemas/Pet"
    },
    "examples": {
      "cat" : {
        "summary": "An example of a cat",
        "value":
          {
            "name": "Fluffy",
            "petType": "Cat",
            "color": "White",
            "gender": "male",
            "breed": "Persian"
          }
      },
      "dog": {
        "summary": "An example of a dog with a cat's name",
        "value" :  {
          "name": "Puma",
          "petType": "Dog",
          "color": "Black",
          "gender": "Female",
          "breed": "Mixed"
        },
      "frog": {
          "$ref": "#/components/examples/frog-example"
        }
      }
    }
  }
}
application/json:
  schema:
    $ref: "#/components/schemas/Pet"
  examples:
    cat:
      summary: An example of a cat
      value:
        name: Fluffy
        petType: Cat
        color: White
        gender: male
        breed: Persian
    dog:
      summary: An example of a dog with a cat's name
      value:
        name: Puma
        petType: Dog
        color: Black
        gender: Female
        breed: Mixed
    frog:
      $ref: "#/components/examples/frog-example"

对文件上传的考虑

相对于2.0的规范,file内容的上传与下载在开放API规范与其他类型一样使用相同的语法来描述。 特别的是:

# content transferred with base64 encoding
schema:
  type: string
  format: base64
# content transferred in binary (octet-stream):
schema:
  type: string
  format: binary

这些示例同时适用于文件上传和下载。

一个使用POST操作提交文件的requestBody看起来像下面这样:

requestBody:
  content:
    application/octet-stream:
      # any media type is accepted, functionally equivalent to `*/*`
      schema:
        # a binary file of any type
        type: string
        format: binary

此外,可以指定明确的媒体类型:

# multiple, specific media types may be specified:
requestBody:
  content:
      # a binary file of type png or jpeg
    'image/jpeg':
      schema:
        type: string
        format: binary
    'image/png':
      schema:
        type: string
        format: binary

为了同时上传多个文件,必须指定multipart媒体类型:

requestBody:
  content:
    multipart/form-data:
      schema:
        properties:
          # The property name 'file' will be used for all files.
          file:
            type: array
            items:
              type: string
              format: binary

x-www-form-urlencoded 请求体的支持

可以使用下面定义的格式来提交form url编码RFC1866的内容:

requestBody:
  content:
    application/x-www-form-urlencoded:
      schema:
        type: object
        properties:
          id:
            type: string
            format: uuid
          address:
            # complex types are stringified to support RFC 1866
            type: object
            properties: {}

在这个示例中,在内容被传送到服务器之前,requestBody中的内容必须使用RFC1866中定义的方式字符串化。此外address字段的复杂对象将会被字符串化。

当使用application/x-www-form-urlencoded格式传送复杂对象时,默认的序列化策略在Encoding Objectstyle 属性中定义为form.

对multipart内容的特别思考

使用multipart/form-data作为Content-Type来传送请求体是很常见的做法。相对于2.0版本的规范,当定义multipart内容的输入参数时必须指定schema属性。这不但支持复杂的结构而且支持多文件上传机制。

当使用multipart类型是,可以使用boundaries来分隔传送的内容,因此multipart定义了以下默认的Content-Type

  • 如果属性是一个原始值或者是一个原始值的数组,那么默认的Content-Type是 text/plain

  • 如果属性是复杂对象或者复杂对象的数组,那么默认的Content-Type是application/json

  • 如果属性是type: stringformat: binaryformat: base64(也就是文件对象)的组合,那么默认的Content-Type是 application/octet-stream

示例:

requestBody:
  content:
    multipart/form-data:
      schema:
        type: object
        properties:
          id:
            type: string
            format: uuid
          address:
            # default Content-Type for objects is `application/json`
            type: object
            properties: {}
          profileImage:
            # default Content-Type for string/binary is `application/octet-stream`
            type: string
            format: binary
          children:
            # default Content-Type for arrays is based on the `inner` type (text/plain here)
            type: array
            items:
              type: string
          addresses:
            # default Content-Type for arrays is based on the `inner` type (object shown, so `application/json` in this example)
            type: array
            items:
              type: '#/components/schemas/Address'

这里介绍一下用来控制序列化multipart请求体的encoding属性,这个属性只适用于multipartapplication/x-www-form-urlencoded类型的请求体。

Encoding 对象

一个编码定义仅适用于一个结构属性。

固定字段

这个对象可能会被规范扩展扩展。

Encoding 对象示例

requestBody:
  content:
    multipart/mixed:
      schema:
        type: object
        properties:
          id:
            # default is text/plain
            type: string
            format: uuid
          address:
            # default is application/json
            type: object
            properties: {}
          historyMetadata:
            # need to declare XML format!
            description: metadata in XML format
            type: object
            properties: {}
          profileImage:
            # default is application/octet-stream, need to declare an image type only!
            type: string
            format: binary
      encoding:
        historyMetadata:
          # require XML Content-Type in utf-8 encoding
          contentType: application/xml; charset=utf-8
        profileImage:
          # only accept png/jpeg
          contentType: image/png, image/jpeg
          headers:
            X-Rate-Limit-Limit:
              description: The number of allowed requests in the current period
              schema:
                type: integer

Responses 对象

描述一个操作可能发生的响应的响应码与响应包含的响应体的对象。

一份API文档不必包含所有可能响应码,因为有些状态码无法提前预知。尽管如此,一份文档还是应当包含所有成功的响应和任何已知的错误响应。

default字段可以用来标记一个响应适用于其他未被规范明确定义的HTTP响应码的默认响应。

一个Responses 对象必须至少包含一个响应码,而且是成功的响应。

固定字段

模式字段

这个对象可能会被规范扩展扩展。

Responses 对象示例

一个代表成功操作的 200 响应和一个代表其他操作状态的默认响应(暗示是一个错误):

{
  "200": {
    "description": "a pet to be returned",
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/Pet"
        }
      }
    }
  },
  "default": {
    "description": "Unexpected error",
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/ErrorModel"
        }
      }
    }
  }
}
'200':
  description: a pet to be returned
  content:
    application/json:
      schema:
        $ref: '#/components/schemas/Pet'
default:
  description: Unexpected error
  content:
    application/json:
      schema:
        $ref: '#/components/schemas/ErrorModel'

Response对象

描述单个API操作的响应,包括设计时间、基于不同响应也包括到相应操作的静态links

固定字段

这个对象可能会被规范扩展扩展。

Response 对象示例s

一个包含复杂类型的数组格式的响应:

{
  "description": "A complex object array response",
  "content": {
    "application/json": {
      "schema": {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/VeryComplexType"
        }
      }
    }
  }
}
description: A complex object array response
content:
  application/json:
    schema:
      type: array
      items:
        $ref: '#/components/schemas/VeryComplexType'

字符串类型的响应:

{
  "description": "A simple string response",
  "content": {
    "text/plain": {
      "schema": {
        "type": "string"
      }
    }
  }

}
description: A simple string response
representations:
  text/plain:
    schema:
      type: string

带HTTP头的普通文本类型的响应:

{
  "description": "A simple string response",
  "content": {
    "text/plain": {
      "schema": {
        "type": "string"
      }
    }
  },
  "headers": {
    "X-Rate-Limit-Limit": {
      "description": "The number of allowed requests in the current period",
      "schema": {
        "type": "integer"
      }
    },
    "X-Rate-Limit-Remaining": {
      "description": "The number of remaining requests in the current period",
      "schema": {
        "type": "integer"
      }
    },
    "X-Rate-Limit-Reset": {
      "description": "The number of seconds left in the current period",
      "schema": {
        "type": "integer"
      }
    }
  }
}
description: A simple string response
content:
  text/plain:
    schema:
      type: string
    example: 'whoa!'
headers:
  X-Rate-Limit-Limit:
    description: The number of allowed requests in the current period
    schema:
      type: integer
  X-Rate-Limit-Remaining:
    description: The number of remaining requests in the current period
    schema:
      type: integer
  X-Rate-Limit-Reset:
    description: The number of seconds left in the current period
    schema:
      type: integer

没有返回值的响应:

{
  "description": "object created"
}
description: object created

Callback 对象

A map of possible out-of band callbacks related to the parent operation. 映射中的每个值都是一个描述一组可能会被API提供者发起的请求和相应的响应的 Path Item Object 。用以标识回调对象的键是一个表达式,表达式会在运行时被计算,得到的值作为回调操作的URL。

模式字段

这个对象可能会被规范扩展扩展。

Key Expression

用于标识 Path Item Object 的键是一个 runtime expression,此表达式会在运行时的HTTP请求/响应上下文中被计算,计算结果用于表示回调请求的URL。 一个简单的例子是 $request.body#/url。 However, using a runtime expression the complete HTTP message can be accessed. This includes accessing any part of a body that a JSON Pointer RFC6901 can reference.

比如有如下 HTTP 请求:

POST /subscribe/myevent?queryUrl=http://clientdomain.com/stillrunning HTTP/1.1
Host: example.org
Content-Type: application/json
Content-Length: 187

{
  "failedUrl" : "http://clientdomain.com/failed",
  "successUrls" : [
    "http://clientdomain.com/fast",
    "http://clientdomain.com/medium",
    "http://clientdomain.com/slow"
  ]
}

201 Created
Location: http://example.org/subscription/1

下方示例展示了各种表达式是如何被计算,这里假设回调操作有一个名为 eventType 的路径参数和一个名为 queryUrl 的查询参数。

Callback 对象示例

如下示例展示了一个通过请求体内的 idemail 属性指定的URL的回调。

myWebhook:
  'http://notificationServer.com?transactionId={$request.body#/id}&email={$request.body#/email}':
    post:
      requestBody:
        description: Callback payload
        content:
          'application/json':
            schema:
              $ref: '#/components/schemas/SomePayload'
      responses:
        '200':
          description: webhook successfully processed and no retries will be performed

Example 对象

固定字段

这个对象可能会被规范扩展扩展。

In all cases, the example value is expected to be compatible with the type schema of its associated value. Tooling implementations MAY choose to validate compatibility automatically, and reject the example value(s) if incompatible.

Example 对象示例

# in a model
schemas:
  properties:
    name:
      type: string
      examples:
        name:
          $ref: http://example.org/petapi-examples/openapi.json#/components/examples/name-example

# in a request body:
  requestBody:
    content:
      'application/json':
        schema:
          $ref: '#/components/schemas/Address'
        examples:
          foo:
            summary: A foo example
            value: {"foo": "bar"}
          bar:
            summary: A bar example
            value: {"bar": "baz"}
      'application/xml':
        examples:
          xmlExample:
            summary: This is an example in XML
            externalValue: 'http://example.org/examples/address-example.xml'
      'text/plain':
        examples:
          textExample:
            summary: This is a text example
            externalValue: 'http://foo.bar/examples/address-example.txt'


# in a parameter
  parameters:
    - name: 'zipCode'
      in: 'query'
      schema:
        type: 'string'
        format: 'zip-code'
        examples:
          zip-example:
            $ref: '#/components/examples/zip-example'

# in a response
  responses:
    '200':
      description: your car appointment has been booked
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SuccessResponse'
          examples:
            confirmation-success:
              $ref: '#/components/examples/confirmation-success'

The Link 对象 represents a possible design-time link for a response. The presence of a link does not guarantee the caller's ability to successfully invoke it, rather it provides a known relationship and traversal mechanism between responses and other operations.

Unlike dynamic links (i.e. links provided in the response payload), the OAS linking mechanism does not require link information in the runtime response.

For computing links, and providing instructions to execute them, a runtime expression is used for accessing values in an operation and using them as parameters while invoking the linked operation.

固定字段

这个对象可能会被规范扩展扩展。

A linked operation MUST be identified using either an operationRef or operationId. In the case of an operationId, it MUST be unique and resolved in the scope of the OAS document. Because of the potential for name clashes, the operationRef syntax is preferred for specifications with external references.

Examples

Computing a link from a request operation where the $request.path.id is used to pass a request parameter to the linked operation.

paths:
  /users/{id}:
    parameters:
    - name: id
      in: path
      required: true
      description: the user identifier, as userId
      schema:
        type: string
    get:
      responses:
        '200':
          description: the user being returned
          content:
            application/json:
              schema:
                type: object
                properties:
                  uuid: # the unique user id
                    type: string
                    format: uuid
        links:
          address:
            # the target link operationId
            operationId: getUserAddress
            parameters:
              # get the `id` field from the request path parameter named `id`
              userId: $request.path.id
  # the path item of the linked operation
  /users/{userid}/address:
    parameters:
    - name: userid
      in: path
      required: true
      description: the user identifier, as userId
      schema:
        type: string
      # linked operation
      get:
        operationId: getUserAddress
        responses:
          '200':
            description: the user's address

When a runtime expression fails to evaluate, no parameter value is passed to the target operation.

Values from the response body can be used to drive a linked operation.

links:
  address:
    operationId: getUserAddressByUUID
    parameters:
      # get the `id` field from the request path parameter named `id`
      userUuid: $response.body#/uuid

Clients follow all links at their discretion. Neither permissions, nor the capability to make a successful call to that link, is guaranteed solely by the existence of a relationship.

OperationRef Examples

As references to operationId MAY NOT be possible (the operationId is an optional value), references MAY also be made through a relative operationRef:

links:
  UserRepositories:
    # returns array of '#/components/schemas/repository'
    operationRef: '#/paths/~12.0~1repositories~1{username}/get'
    parameters:
      username: $response.body#/username

or an absolute operationRef:

links:
  UserRepositories:
    # returns array of '#/components/schemas/repository'
    operationRef: 'https://na2.gigantic-server.com/#/paths/~12.0~1repositories~1{username}/get'
    parameters:
      username: $response.body#/username

Note that in the use of operationRef, the escaped forward-slash is necessary when using JSON references.

Runtime Expressions

Runtime expressions allow defining values based on information that will only be available within the HTTP message in an actual API call. This mechanism is used by Link Objects and Callback Objects.

The runtime expression is defined by the following ABNF syntax

      expression = ( "$url" | "$method" | "$statusCode" | "$request." source | "$response." source )
      source = ( header-reference | query-reference | path-reference | body-reference )
      header-reference = "header." token
      query-reference = "query." name
      path-reference = "path." name
      body-reference = "body" ["#" fragment]
      fragment = a JSON Pointer [RFC 6901](https://tools.ietf.org/html/rfc6901)
      name = *( char )
      char = as per RFC [7159](https://tools.ietf.org/html/rfc7159#section-7)
      token = as per RFC [7230](https://tools.ietf.org/html/rfc7230#section-3.2.6)

The name identifier is case-sensitive, whereas token is not.

The table below provides examples of runtime expressions and examples of their use in a value:

Examples

Runtime expressions preserve the type of the referenced value. Expressions can be embedded into string values by surrounding the expression with {} curly braces.

Header 对象

Header 对象除了以下改动之外与 Parameter 对象 一致:

  1. name 不能被指定,它在相应的 headers 映射中被指定。

  2. in 不能被指定,它隐含在 header 中。

  3. 所有被 location 影响的特性必须适合 header 中的一个 location,(比如 style)。

Header 对象示例

一个类型为 integer 的简单 header:

{
  "description": "The number of allowed requests in the current period",
  "schema": {
    "type": "integer"
  }
}
description: The number of allowed requests in the current period
schema:
  type: integer

Tag Object

Adds metadata to a single tag that is used by the Operation Object. It is not mandatory to have a Tag Object per tag defined in the Operation Object instances.

固定字段

这个对象可能会被规范扩展扩展。

Tag 对象示例

{
  "name": "pet",
  "description": "Pets operations"
}
name: pet
description: Pets operations

Examples Object

In an example, a JSON Reference MAY be used, with the explicit restriction that examples having a JSON format with object named $ref are not allowed. Therefore, that example, structurally, can be either a string primitive or an object, similar to additionalProperties.

In all cases, the payload is expected to be compatible with the type schema for the associated value. Tooling implementations MAY choose to validate compatibility automatically, and reject the example value(s) if they are incompatible.

# in a model
schemas:
  properties:
    name:
      type: string
      example:
        $ref: http://foo.bar#/examples/name-example

# in a request body, note the plural `examples`
  requestBody:
    content:
      'application/json':
        schema:
          $ref: '#/components/schemas/Address'
        examples:
          foo:
            value: {"foo": "bar"}
          bar:
            value: {"bar": "baz"}
      'application/xml':
        examples:
          xml:
            externalValue: 'http://foo.bar/examples/address-example.xml'
      'text/plain':
        examples:
          text:
            externalValue: 'http://foo.bar/examples/address-example.txt'

# in a parameter
  parameters:
    - name: 'zipCode'
      in: 'query'
      schema:
        type: 'string'
        format: 'zip-code'
        example:
          $ref: 'http://foo.bar#/examples/zip-example'

# in a response, note the singular `example`:
  responses:
    '200':
      description: your car appointment has been booked
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SuccessResponse'
          example:
            $ref: http://foo.bar#/examples/address-example.json

Reference 对象

一个允许引用规范内部的其他部分或外部规范的对象。

Reference Object 定义于 JSON Reference 且遵循相同的结构、行为和规则。

For this specification, reference resolution is accomplished as defined by the JSON Reference specification and not by the JSON Schema specification.

固定字段

此对象不能被扩展,任何附加的属性将会被忽略。

Reference 对象示例

{
  "$ref": "#/components/schemas/Pet"
}
$ref: '#/components/schemas/Pet'

关联外部文档示例

{
  "$ref": "Pet.json"
}
$ref: Pet.yaml

关联外部文档的一部分

{
  "$ref": "definitions.json#/Pet"
}
$ref: definitions.yaml#/Pet

Schema Object

Schema Object 用于定义输入和输出的数据类型。这些类型可以是对象,但也可以是原始值和数组。这个对象是 JSON Schema Specification Wright Draft 00 扩展后的子集.

关于property的的更多信息请查看 JSON Schema CoreJSON Schema Validation。除非另有说明,否则 properties 定义遵循JSON Schema。

Properties

以下 properties 是直接从 JSON Schema 提取出来的,而且遵循同样的规范:

  • title

  • multipleOf

  • maximum

  • exclusiveMaximum

  • minimum

  • exclusiveMinimum

  • maxLength

  • minLength

  • pattern (This string SHOULD be a valid regular expression, according to the ECMA 262 regular expression dialect)

  • maxItems

  • minItems

  • uniqueItems

  • maxProperties

  • minProperties

  • required

  • enum

以下 properties 是从 JSON Schema 提取出来的,但是做了一些调整以适应 OpenAPI Specification。

  • type - 值必须是一个字符串,不支持以数组形式定义多个值。

  • allOf - Inline 或 referenced 的 schema 必须是一个 Schema Object 且不是一个标准的 JSON Schema。

  • oneOf - Inline 或 referenced 的 schema 必须是一个 Schema Object 且不是一个标准的 JSON Schema。

  • anyOf - Inline 或 referenced 的 schema 必须是一个 Schema Object 且不是一个标准的 JSON Schema。

  • not - Inline 或 referenced 的 schema 必须是一个 Schema Object 且不是一个标准的 JSON Schema。

  • items - 值必须是一个对象且不是一个数组。Inline 或 referenced 的 schema 必须是一个 Schema Object且不是一个标准的 JSON Schem。. items 必须存在如果 type 的值是 array

  • properties - Property 定义必须是一个 Schema Object 且不是一个标准的 JSON Schema (inline 或 referenced).

  • additionalProperties - 值可以是 boolean 或 object. Inline 或 referenced schema 必须是一个 Schema Object 且不是一个标准的 JSON Schema。

  • description - CommonMark syntax可以被用来呈现富文本格式.

  • format - 查看 Data Type Formats 以深入了解细节。在依靠 JSON Schema 定义的格式的同时,OAS 额外提供了一些预定义的格式。

  • default - The default value represents what would be assumed by the consumer of the input as the value of the schema if one is not provided. 不同于 JSON Schema,这个值必须符合定义与相同级别的 Schema Object 中定义的类型,比如 typestring,那么 default 可以是 "foo" 但不能是 1

另外,任何可以使用 Schema Object 的地方也可以使用 Reference Object 替代。这允许引用一个定义而避免重复定义。

未在此处提及的 JSON Schema 规范中定义的其他属性将严格的不被支持。

Other than the JSON Schema subset fields, 以下字段可能会被用于后续的 schema documentation:

固定字段

这个对象可能会被规范扩展扩展。

Composition and Inheritance (Polymorphism)

The OpenAPI Specification allows combining and extending model definitions using the allOf property of JSON Schema, in effect offering model composition. allOf takes an array of object definitions that are validated independently but together compose a single object.

While composition offers model extensibility, it does not imply a hierarchy between the models. To support polymorphism, the OpenAPI Specification adds the discriminator field. When used, the discriminator will be the name of the property that decides which schema definition validates the structure of the model. As such, the discriminator field MUST be a required field. There are are two ways to define the value of a discriminator for an inheriting instance.

  • Use the schema name.

  • Override the schema name by overriding the property with a new value. If a new value exists, this takes precedence over the schema name.

    As such, inline schema definitions, which do not have a given id, cannot be used in polymorphism.

XML Modeling

The xml property allows extra definitions when translating the JSON definition to XML. The XML Object contains additional information about the available options.

Schema 对象示例s

Primitive Sample

{
  "type": "string",
  "format": "email"
}
type: string
format: email

Simple Model

{
  "type": "object",
  "required": [
    "name"
  ],
  "properties": {
    "name": {
      "type": "string"
    },
    "address": {
      "$ref": "#/components/schemas/Address"
    },
    "age": {
      "type": "integer",
      "format": "int32",
      "minimum": 0
    }
  }
}
type: object
required:
- name
properties:
  name:
    type: string
  address:
    $ref: '#/components/schemas/Address'
  age:
    type: integer
    format: int32
    minimum: 0

Model with Map/Dictionary Properties

For a simple string to string mapping:

{
  "type": "object",
  "additionalProperties": {
    "type": "string"
  }
}
type: object
additionalProperties:
  type: string

For a string to model mapping:

{
  "type": "object",
  "additionalProperties": {
    "$ref": "#/components/schemas/ComplexModel"
  }
}
type: object
additionalProperties:
  $ref: '#/components/schemas/ComplexModel'

Model with Example

{
  "type": "object",
  "properties": {
    "id": {
      "type": "integer",
      "format": "int64"
    },
    "name": {
      "type": "string"
    }
  },
  "required": [
    "name"
  ],
  "example": {
    "name": "Puma",
    "id": 1
  }
}
type: object
properties:
  id:
    type: integer
    format: int64
  name:
    type: string
required:
- name
example:
  name: Puma
  id: 1

Models with Composition

{
  "components": {
    "schemas": {
      "ErrorModel": {
        "type": "object",
        "required": [
          "message",
          "code"
        ],
        "properties": {
          "message": {
            "type": "string"
          },
          "code": {
            "type": "integer",
            "minimum": 100,
            "maximum": 600
          }
        }
      },
      "ExtendedErrorModel": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ErrorModel"
          },
          {
            "type": "object",
            "required": [
              "rootCause"
            ],
            "properties": {
              "rootCause": {
                "type": "string"
              }
            }
          }
        ]
      }
    }
  }
}
components:
  schemas:
    ErrorModel:
      type: object
      required:
      - message
      - code
      properties:
        message:
          type: string
        code:
          type: integer
          minimum: 100
          maximum: 600
    ExtendedErrorModel:
      allOf:
      - $ref: '#/components/schemas/ErrorModel'
      - type: object
        required:
        - rootCause
        properties:
          rootCause:
            type: string

Models with Polymorphism Support

{
  "components": {
    "schemas": {
      "Pet": {
        "type": "object",
        "discriminator": {
          "propertyName": "petType"
        },
        "properties": {
          "name": {
            "type": "string"
          },
          "petType": {
            "type": "string"
          }
        },
        "required": [
          "name",
          "petType"
        ]
      },
      "Cat": {
        "description": "A representation of a cat. Note that `Cat` will be used as the discriminator value.",
        "allOf": [
          {
            "$ref": "#/components/schemas/Pet"
          },
          {
            "type": "object",
            "properties": {
              "huntingSkill": {
                "type": "string",
                "description": "The measured skill for hunting",
                "default": "lazy",
                "enum": [
                  "clueless",
                  "lazy",
                  "adventurous",
                  "aggressive"
                ]
              }
            },
            "required": [
              "huntingSkill"
            ]
          }
        ]
      },
      "Dog": {
        "description": "A representation of a dog. Note that `Dog` will be used as the discriminator value.",
        "allOf": [
          {
            "$ref": "#/components/schemas/Pet"
          },
          {
            "type": "object",
            "properties": {
              "packSize": {
                "type": "integer",
                "format": "int32",
                "description": "the size of the pack the dog is from",
                "default": 0,
                "minimum": 0
              }
            },
            "required": [
              "packSize"
            ]
          }
        ]
      }
    }
  }
}
components:
  schemas:
    Pet:
      type: object
      discriminator:
        propertyName: petType
      properties:
        name:
          type: string
        petType:
          type: string
      required:
      - name
      - petType
    Cat:  ## "Cat" will be used as the discriminator value
      description: A representation of a cat
      allOf:
      - $ref: '#/components/schemas/Pet'
      - type: object
        properties:
          huntingSkill:
            type: string
            description: The measured skill for hunting
            enum:
            - clueless
            - lazy
            - adventurous
            - aggressive
        required:
        - huntingSkill
    Dog:  ## "Dog" will be used as the discriminator value
      description: A representation of a dog
      allOf:
      - $ref: '#/components/schemas/Pet'
      - type: object
        properties:
          packSize:
            type: integer
            format: int32
            description: the size of the pack the dog is from
            default: 0
            minimum: 0
        required:
        - packSize

Discriminator 对象

当一个 request bodies 或 response payloads 可以是多种 schemas 时,可以使用一个 discriminator 对象来帮助序列化、反序列化和校验。 The discriminator is a specific object in a schema which is used to inform the consumer of the specification of an alternative schema based on the value associated with it.

当使用 discriminator 时,inline schemas 不会被考虑。

固定字段

discriminator 属性仅在与 oneOf, anyOf, allOf 这几个复合关键字之一一起使用时才合法.

在 OAS 3.0 中,一个 response payload 仅可以使用一种类型来描述:

MyResponseType:
  oneOf:
  - $ref: '#/components/schemas/Cat'
  - $ref: '#/components/schemas/Dog'
  - $ref: '#/components/schemas/Lizard'

也就是说 payload 必须 且只能满足 CatDogLizzard schemas 中的一个。 In this case, a discriminator MAY act as a "hint" to shortcut validation and selection of the matching schema which may be a costly operation, depending on the complexity of the schema. We can then describe exactly which field tells us which schema to use:

MyResponseType:
  oneOf:
  - $ref: '#/components/schemas/Cat'
  - $ref: '#/components/schemas/Dog'
  - $ref: '#/components/schemas/Lizard'
  discriminator:
    propertyName: pet_type

The expectation now is that a property with name pet_type MUST be present in the response payload, and the value will correspond to the name of a schema defined in the OAS document. Thus the response payload:

{
  "id": 12345,
  "pet_type": "Cat"
}

Will indicate that the Cat schema be used in conjunction with this payload.

In scenarios where the value of the discriminator field does not match the schema name or implicit mapping is not possible, an optional mapping definition MAY be used:

MyResponseType:
  oneOf:
  - $ref: '#/components/schemas/Cat'
  - $ref: '#/components/schemas/Dog'
  - $ref: '#/components/schemas/Lizard'
  - $ref: 'https://gigantic-server.com/schemas/Monster/schema.json'
  discriminator:
    propertyName: pet_type
    mapping:
      dog: '#/components/schemas/Dog'
      monster: 'https://gigantic-server.com/schemas/Monster/schema.json'

Here the discriminator value of dog will map to the schema #/components/schemas/Dog, rather than the default (implicit) value of Dog. If the discriminator value does not match an implicit or explicit mapping, no schema can be determined and validation SHOULD fail. Mapping keys MUST be string values, but tooling MAY convert response values to strings for comparison.

When used in conjunction with the anyOf construct, the use of the discriminator can avoid ambiguity where multiple schemas may satisfy a single payload.

In both the oneOf and anyOf use cases, all possible schemas MUST be listed explicitly. To avoid redundancy, the discriminator MAY be added to a parent schema definition, and all schemas comprising the parent schema in an allOf construct may be used as an alternate schema.

For example:

components:
  schemas:
    Pet:
      type: object
      required:
      - pet_type
      properties:
        pet_type:
          type: string
      discriminator:
        propertyName: pet_type
        mapping:
          cachorro: Dog
    Cat:
      allOf:
      - $ref: '#/components/schemas/Pet'
      - type: object
        # all other properties specific to a `Cat`
        properties:
          name:
            type: string
    Dog:
      allOf:
      - $ref: '#/components/schemas/Pet'
      - type: object
        # all other properties specific to a `Dog`
        properties:
          bark:
            type: string
    Lizard:
      allOf:
      - $ref: '#/components/schemas/Pet'
      - type: object
        # all other properties specific to a `Lizard`
        properties:
          lovesRocks:
            type: boolean

a payload like this:

{
  "pet_type": "Cat",
  "name": "misty"
}

will indicate that the Cat schema be used. Likewise this schema:

{
  "pet_type": "cachorro",
  "bark": "soft"
}

will map to Dog because of the definition in the mappings element.

XML 对象

一个为 XML 模型定义微调过的元数据对象。

当使用数组时,不会推测 XML 元素的名称(单数或复数形式),所以应该添加 name 属性来提供此信息。 查看展示此期望的示例。

固定字段

这个对象可能会被规范扩展扩展。

XML 对象示例

XML 对象定义的示例被包括在一个 Schema 对象 的特性定义并带有一个样例 XML 来呈现它。

无 XML 元素

基础字符串属性:

{
    "animals": {
        "type": "string"
    }
}
animals:
  type: string
<animals>...</animals>

基础字符串数组属性 (wrapped 默认是 false):

{
    "animals": {
        "type": "array",
        "items": {
            "type": "string"
        }
    }
}
animals:
  type: array
  items:
    type: string
<animals>...</animals>
<animals>...</animals>
<animals>...</animals>

XML 名称替换

{
  "animals": {
    "type": "string",
    "xml": {
      "name": "animal"
    }
  }
}
animals:
  type: string
  xml:
    name: animal
<animal>...</animal>

XML 属性,前缀和命名空间

在此示例中展示了一个完整的模型定义。

{
  "Person": {
    "type": "object",
    "properties": {
      "id": {
        "type": "integer",
        "format": "int32",
        "xml": {
          "attribute": true
        }
      },
      "name": {
        "type": "string",
        "xml": {
          "namespace": "http://example.com/schema/sample",
          "prefix": "sample"
        }
      }
    }
  }
}
Person:
  type: object
  properties:
    id:
      type: integer
      format: int32
      xml:
        attribute: true
    name:
      type: string
      xml:
        namespace: http://example.com/schema/sample
        prefix: sample
<Person id="123">
    <sample:name xmlns:sample="http://example.com/schema/sample">example</sample:name>
</Person>

XML 数组

改变元素的名称:

{
  "animals": {
    "type": "array",
    "items": {
      "type": "string",
      "xml": {
        "name": "animal"
      }
    }
  }
}
animals:
  type: array
  items:
    type: string
    xml:
      name: animal
<animal>value</animal>
<animal>value</animal>

外部的 name 属性在 XML 上不产生效果:

{
  "animals": {
    "type": "array",
    "items": {
      "type": "string",
      "xml": {
        "name": "animal"
      }
    },
    "xml": {
      "name": "aliens"
    }
  }
}
animals:
  type: array
  items:
    type: string
    xml:
      name: animal
  xml:
    name: aliens
<animal>value</animal>
<animal>value</animal>

尽管数组是被包裹的,如果没有明确定义一个名称,那么同样地名称会被用于内部和外部:

{
  "animals": {
    "type": "array",
    "items": {
      "type": "string"
    },
    "xml": {
      "wrapped": true
    }
  }
}
animals:
  type: array
  items:
    type: string
  xml:
    wrapped: true
<animals>
  <animals>value</animals>
  <animals>value</animals>
</animals>

为了解决上面示例的命名问题,可以使用下面的定义:

{
  "animals": {
    "type": "array",
    "items": {
      "type": "string",
      "xml": {
        "name": "animal"
      }
    },
    "xml": {
      "wrapped": true
    }
  }
}
animals:
  type: array
  items:
    type: string
    xml:
      name: animal
  xml:
    wrapped: true
<animals>
  <animal>value</animal>
  <animal>value</animal>
</animals>

Affecting both internal and external names:

{
  "animals": {
    "type": "array",
    "items": {
      "type": "string",
      "xml": {
        "name": "animal"
      }
    },
    "xml": {
      "name": "aliens",
      "wrapped": true
    }
  }
}
animals:
  type: array
  items:
    type: string
    xml:
      name: animal
  xml:
    name: aliens
    wrapped: true
<aliens>
  <animal>value</animal>
  <animal>value</animal>
</aliens>

如果我们改变外部的元素而保持内部的不变:

{
  "animals": {
    "type": "array",
    "items": {
      "type": "string"
    },
    "xml": {
      "name": "aliens",
      "wrapped": true
    }
  }
}
animals:
  type: array
  items:
    type: string
  xml:
    name: aliens
    wrapped: true
<aliens>
  <aliens>value</aliens>
  <aliens>value</aliens>
</aliens>

Security Scheme 对象

定义一个用于 operations 的 security scheme。被支持的 schemes 有 HTTP 认证,一个 API key(作为 header 或 query parameter),定义于RFC6749 的 Oauth2 常用流程(implicit、password、application 和 access code)和 OpenID Connect Discovery

固定字段

这个对象可能会被规范扩展扩展。

Security Scheme 对象示例

Basic Authentication Sample

{
  "type": "http",
  "scheme": "basic"
}
type: http
scheme: basic

API Key Sample

{
  "type": "apiKey",
  "name": "api_key",
  "in": "header"
}
type: apiKey
name: api_key
in: header

JWT Bearer Sample

{
  "type": "http",
  "scheme": "bearer",
  "bearerFormat": "JWT",
}
type: http
scheme: bearer
bearerFormat: JWT

Implicit OAuth2 Sample

{
  "type": "oauth2",
  "flows": {
    "implicit": {
      "authorizationUrl": "https://example.com/api/oauth/dialog",
      "scopes": {
        "write:pets": "modify pets in your account",
        "read:pets": "read your pets"
      }
    }
  }
}
type: oauth2
flows:
  implicit:
    authorizationUrl: https://example.com/api/oauth/dialog
    scopes:
      write:pets: modify pets in your account
      read:pets: read your pets

OAuth Flows 对象

允许配置支持的 OAuth Flows。

固定字段

这个对象可能会被规范扩展扩展。

OAuth Flow 对象

支持的 OAuth Flow 的配置详情。

固定字段

这个对象可能会被规范扩展扩展。

OAuth Flow 对象示例s

{
  "type": "oauth2",
  "flows": {
    "implicit": {
      "authorizationUrl": "https://example.com/api/oauth/dialog",
      "scopes": {
        "write:pets": "modify pets in your account",
        "read:pets": "read your pets"
      }
    },
    "authorizationCode": {
      "authorizationUrl": "https://example.com/api/oauth/dialog",
      "tokenUrl": "https://example.com/api/oauth/token",
      "scopes": {
        "write:pets": "modify pets in your account",
        "read:pets": "read your pets"
      }
    }
  }
}
type: oauth2
flows:
  implicit:
    authorizationUrl: https://example.com/api/oauth/dialog
    scopes:
      write:pets: modify pets in your account
      read:pets: read your pets
  authorizationCode:
    authorizationUrl: https://example.com/api/oauth/dialog
    tokenUrl: https://example.com/api/oauth/token
    scopes:
      write:pets: modify pets in your account
      read:pets: read your pets

Security Requirement 对象

列出执行此 operation 所需的 security schemes。每个属性的名字都必须与 Components ObjectSecurity Schemes 声明的 security scheme 相符。

包含多个 schemes 的 Security Requirement 对象中的所有 scheme 都必须要满足授权请求。这便能够支持需要使用多个 query parameters 或 HTTP headers 来传递安全信息的情景。

当When a list of Security Requirement Objects is defined on the Open API 对象 或 [Operation 对象] (#operationObject) 包含一组 Security Requirement 对象时,请求只需要满足其中一个即可。

模式字段

Security Requirement 对象示例

Non-OAuth2 Security Requirement

{
  "api_key": []
}
api_key: []

OAuth2 Security Requirement

{
  "petstore_auth": [
    "write:pets",
    "read:pets"
  ]
}
petstore_auth:
- write:pets
- read:pets

规范扩展

尽管 OpenAPI Specification 尝试包含大部分的使用场景,在需要时仍然可以通过附加数据来扩展此规范。

此扩展属性被设计为总是以 "x-" 为前缀的模式字段。

此扩展可能会也可能不会被当前的工具支持,但是可以请求工具开发者支持此扩展(如果工具是内部或开源的)。

Security Filtering

Some objects in the OpenAPI Specification MAY be declared and remain empty, or be completely removed, even though they are inherently the core of the API documentation.

The reasoning is to allow an additional layer of access control over the documentation. While not part of the specification itself, certain libraries MAY choose to allow access to parts of the documentation based on some form of authentication/authorization.

Two examples of this:

  1. The Paths Object MAY be empty. It may be counterintuitive, but this may tell the viewer that they got to the right place, but can't access any documentation. They'd still have access to the Info Object which may contain additional information regarding authentication.

  2. The Path Item Object MAY be empty. In this case, the viewer will be aware that the path exists, but will not be able to see any of its operations or parameters. This is different than hiding the path itself from the Paths Object, so the user will not be aware of its existence. This allows the documentation provider to finely control what the viewer can see.

Appendix A: Revision History

Last updated