diff --git a/src/oas.md b/src/oas.md index 9192a1b013..ab59ebc227 100644 --- a/src/oas.md +++ b/src/oas.md @@ -141,6 +141,14 @@ In order to preserve the ability to round-trip between YAML and JSON formats, YA **Note:** While APIs may be described by OpenAPI Descriptions in either YAML or JSON format, the API request and response bodies and other content are not required to be JSON or YAML. +### Rich Text Formatting + +Throughout the specification `description` fields are noted as supporting CommonMark markdown formatting. +Where OpenAPI tooling renders rich text it MUST support, at a minimum, markdown syntax as described by [CommonMark 0.27](https://spec.commonmark.org/0.27/). Tooling MAY choose to ignore some CommonMark or extension features to address security concerns. + +While the framing of CommonMark 0.27 as a minimum requirement means that tooling MAY choose to implement extensions on top of it, note that any such extensions are by definition implementation-defined and will not be interoperable. +OpenAPI Description authors SHOULD consider how text using such extensions will be rendered by tools that offer only the minimum support. + ### OpenAPI Description Structure An OpenAPI Description (OAD) MAY be made up of a single JSON or YAML document or be divided into multiple, connected parts at the discretion of the author. In the latter case, [Reference Object](#reference-object), [Path Item Object](#path-item-object) and [Schema Object](#schema-object) `$ref` fields, as well as the [Link Object](#link-object) `operationRef` field, and the URI form of the [Discriminator Object](#discriminator-object) `mapping` field, are used to identify the referenced elements. @@ -222,82 +230,6 @@ The behavior for Discrimator Object non-URI mappings and for the Operation Objec Note that no aspect of implicit connection resolution changes how [URIs are resolved](#relative-references-in-api-description-uris), or restricts their possible targets. -### Data Types - -Data types in the OAS are based on the types defined by the [JSON Schema Validation Specification Draft 2020-12](https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-validation-00#section-6.1.1): -"null", "boolean", "object", "array", "number", "string", or "integer". -Models are defined using the [Schema Object](#schema-object), which is a superset of the JSON Schema Specification Draft 2020-12. - -JSON Schema keywords and `format` values operate on JSON "instances" which may be one of the six JSON data types, "null", "boolean", "object", "array", "number", or "string", with certain keywords and formats only applying to a specific type. For example, the `pattern` keyword and the `date-time` format only apply to strings, and treat any instance of the other five types as _automatically valid._ This means JSON Schema keywords and formats do **NOT** implicitly require the expected type. Use the `type` keyword to explicitly constrain the type. - -Note that the `type` keyword allows `"integer"` as a value for convenience, but keyword and format applicability does not recognize integers as being of a distinct JSON type from other numbers because [[RFC7159|JSON]] itself does not make that distinction. Since there is no distinct JSON integer type, JSON Schema defines integers mathematically. This means that both `1` and `1.0` are [equivalent](https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-00#section-4.2.2), and are both considered to be integers. - -#### Data Type Format - -As defined by the [JSON Schema Validation specification](https://tools.ietf.org/html/draft-bhutton-json-schema-validation-00#section-7.3), data types can have an optional modifier keyword: `format`. As described in that specification, `format` is treated as a non-validating annotation by default; the ability to validate `format` varies across implementations. - -The OpenAPI Initiative also hosts a [Format Registry](https://spec.openapis.org/registry/format/) for formats defined by OAS users and other specifications. Support for any registered format is strictly OPTIONAL, and support for one registered format does not imply support for any others. - -Types that are not accompanied by a `format` keyword follow the type definition in the JSON Schema. Tools that do not recognize a specific `format` MAY default back to the `type` alone, as if the `format` is not specified. -For the purpose of [JSON Schema validation](https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-validation-00#section-7.1), each format should specify the set of JSON data types for which it applies. In this registry, these types are shown in the "JSON Data Type" column. - -The formats defined by the OAS are: - -| `format` | JSON Data Type | Comments | -| ---- | ---- | ---- | -| `int32` | number | signed 32 bits | -| `int64` | number | signed 64 bits (a.k.a long) | -| `float` | number | | -| `double` | number | | -| `password` | string | A hint to obscure the value. | - -As noted under [Data Type](#data-types), both `type: number` and `type: integer` are considered to be numbers in the data model. - -#### Working with Binary Data - -The OAS can describe either _raw_ or _encoded_ binary data. - -* **raw binary** is used where unencoded binary data is allowed, such as when sending a binary payload as the entire HTTP message body, or as part of a `multipart/*` payload that allows binary parts -* **encoded binary** is used where binary data is embedded in a text-only format such as `application/json` or `application/x-www-form-urlencoded` (either as a message body or in the URL query string). - -In the following table showing how to use Schema Object keywords for binary data, we use `image/png` as an example binary media type. Any binary media type, including `application/octet-stream`, is sufficient to indicate binary content. - -| Keyword | Raw | Encoded | Comments | -| ---- | ---- | ---- | ---- | -| `type` | _omit_ | `string` | raw binary is [outside of `type`](https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-00#section-4.2.3) | -| `contentMediaType` | `image/png` | `image/png` | can sometimes be omitted if redundant (see below) | -| `contentEncoding` | _omit_ | `base64` or `base64url` | other encodings are [allowed](https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-validation-00#section-8.3) | - -Note that the encoding indicated by `contentEncoding`, which inflates the size of data in order to represent it as 7-bit ASCII text, is unrelated to HTTP's `Content-Encoding` header, which indicates whether and how a message body has been compressed and is applied after all content serialization described in this section has occurred. Since HTTP allows unencoded binary message bodies, there is no standardized HTTP header for indicating base64 or similar encoding of an entire message body. - -Using a `contentEncoding` of `base64url` ensures that URL encoding (as required in the query string and in message bodies of type `application/x-www-form-urlencoded`) does not need to further encode any part of the already-encoded binary data. - -The `contentMediaType` keyword is redundant if the media type is already set: - -* as the key for a [MediaType Object](#media-type-object) -* in the `contentType` field of an [Encoding Object](#encoding-object) - -If the [Schema Object](#schema-object) will be processed by a non-OAS-aware JSON Schema implementation, it may be useful to include `contentMediaType` even if it is redundant. However, if `contentMediaType` contradicts a relevant Media Type Object or Encoding Object, then `contentMediaType` SHALL be ignored. - -The `maxLength` keyword MAY be used to set an expected upper bound on the length of a streaming payload. The keyword can be applied to either string data, including encoded binary data, or to unencoded binary data. For unencoded binary, the length is the number of octets. - -##### Migrating binary descriptions from OAS 3.0 - -The following table shows how to migrate from OAS 3.0 binary data descriptions, continuing to use `image/png` as the example binary media type: - -| OAS < 3.1 | OAS >= 3.1 | Comments | -| ---- | ---- | ---- | -| type: string
format: binary | contentMediaType: image/png | if redundant, can be omitted, often resulting in an empty [Schema Object](#schema-object) | -| type: string
format: byte | type: string
contentMediaType: image/png
contentEncoding: base64 | note that `base64url` can be used to avoid re-encoding the base64 string to be URL-safe | - -### Rich Text Formatting - -Throughout the specification `description` fields are noted as supporting CommonMark markdown formatting. -Where OpenAPI tooling renders rich text it MUST support, at a minimum, markdown syntax as described by [CommonMark 0.27](https://spec.commonmark.org/0.27/). Tooling MAY choose to ignore some CommonMark or extension features to address security concerns. - -While the framing of CommonMark 0.27 as a minimum requirement means that tooling MAY choose to implement extensions on top of it, note that any such extensions are by definition implementation-defined and will not be interoperable. -OpenAPI Description authors SHOULD consider how text using such extensions will be rendered by tools that offer only the minimum support. - ### Relative References in API Description URIs URIs used as references within an OpenAPI Description, or to external documentation or other supplementary information such as a license, are resolved as _identifiers_, and described by this specification as **_URIs_**. @@ -1616,64 +1548,7 @@ application/json: $ref: '#/components/examples/frog-example' ``` -##### Considerations for File Uploads - -In contrast to OpenAPI 2.0, `file` input/output content in OAS 3.x is described with the same semantics as any other schema type. - -In contrast to OAS 3.0, the `format` keyword has no effect on the content-encoding of the schema in OAS 3.1. Instead, JSON Schema's `contentEncoding` and `contentMediaType` keywords are used. See [Working With Binary Data](#working-with-binary-data) for how to model various scenarios with these keywords, and how to migrate from the previous `format` usage. - -Examples: - -Content transferred in binary (octet-stream) MAY omit `schema`: - -```yaml -# a PNG image as a binary file: -content: - image/png: {} -``` - -```yaml -# an arbitrary binary file: -content: - application/octet-stream: {} -``` - -```yaml -# arbitrary JSON without constraints beyond being syntactically valid: -content: - application/json: {} -``` - -These examples apply to either input payloads of file uploads or response payloads. - -A `requestBody` for submitting a file in a `POST` operation may look like the following example: - -```yaml -requestBody: - content: - application/octet-stream: {} -``` - -In addition, specific media types MAY be specified: - -```yaml -# multiple, specific media types may be specified: -requestBody: - content: - # a binary file of type png or jpeg - image/jpeg: {} - image/png: {} -``` - -To upload multiple files, a `multipart` media type MUST be used as shown under [Example: Multipart Form with Multiple Files](#example-multipart-form-with-multiple-files). - -##### Support for x-www-form-urlencoded Request Bodies - -See [Encoding the `x-www-form-urlencoded` Media Type](#encoding-the-x-www-form-urlencoded-media-type) for guidance and examples, both with and without the `encoding` field. - -##### Special Considerations for `multipart` Content - -See [Encoding `multipart` Media Types](#encoding-multipart-media-types) for further guidance and examples, both with and without the `encoding` field. +For additional techniques and examples, see [Modeling Non-JSON Data](#modeling-non-json-data). #### Encoding Object @@ -1726,285 +1601,87 @@ See also [Appendix C: Using RFC6570 Implementations](#appendix-c-using-rfc6570-b Note that the presence of at least one of `style`, `explode`, or `allowReserved` with an explicit value is equivalent to using `schema` with `in: "query"` Parameter Objects. The absence of all three of those fields is the equivalent of using `content`, but with the media type specified in `contentType` rather than through a Media Type Object. -##### Encoding the `x-www-form-urlencoded` Media Type - -To submit content using form url encoding via [RFC1866](https://tools.ietf.org/html/rfc1866), use the `application/x-www-form-urlencoded` media type in the [Media Type Object](#media-type-object) under the [Request Body Object](#request-body-object). -This configuration means that the request body MUST be encoded per [RFC1866](https://tools.ietf.org/html/rfc1866) when passed to the server, after any complex objects have been serialized to a string representation. +For additional techniques and examples, see [Modeling Non-JSON Data](#modeling-non-json-data). -See [Appendix E](#appendix-e-percent-encoding-and-form-media-types) for a detailed examination of percent-encoding concerns for form media types. +#### Responses Object -###### Example: URL Encoded Form with JSON Values +A container for the expected responses of an operation. +The container maps a HTTP response code to the expected response. -When there is no [`encoding`](#media-type-encoding) field, the serialization strategy is based on the Encoding Object's default values: +The documentation is not necessarily expected to cover all possible HTTP response codes because they may not be known in advance. +However, documentation is expected to cover a successful operation response and any known errors. -```yaml -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: {} -``` +The `default` MAY be used as a default Response Object for all HTTP codes +that are not covered individually by the Responses Object. -With this example, consider an `id` of `f81d4fae-7dec-11d0-a765-00a0c91e6bf6` and a US-style address (with ZIP+4) as follows: +The Responses Object MUST contain at least one response code, and if only one +response code is provided it SHOULD be the response for a successful operation +call. -```json -{ - "streetAddress": "123 Example Dr.", - "city": "Somewhere", - "state": "CA", - "zip": "99999+1234" -} -``` +##### Fixed Fields -Assuming the most compact representation of the JSON value (with unnecessary whitespace removed), we would expect to see the following request body, where space characters have been replaced with `+` and `+`, `"`, `{`, and `}` have been percent-encoded to `%2B`, `%22`, `%7B`, and `%7D`, respectively: +| Field Name | Type | Description | +| ---- | :----: | ---- | +| default | [Response Object](#response-object) \| [Reference Object](#reference-object) | The documentation of responses other than the ones declared for specific HTTP response codes. Use this field to cover undeclared responses. | -```uri -id=f81d4fae-7dec-11d0-a765-00a0c91e6bf6&address=%7B%22streetAddress%22:%22123+Example+Dr.%22,%22city%22:%22Somewhere%22,%22state%22:%22CA%22,%22zip%22:%2299999%2B1234%22%7D -``` +##### Patterned Fields -Note that the `id` keyword is treated as `text/plain` per the [Encoding Object](#encoding-object)'s default behavior, and is serialized as-is. -If it were treated as `application/json`, then the serialized value would be a JSON string including quotation marks, which would be percent-encoded as `%22`. +| Field Pattern | Type | Description | +| ---- | :----: | ---- | +| [HTTP Status Code](#http-status-codes) | [Response Object](#response-object) \| [Reference Object](#reference-object) | Any [HTTP status code](#http-status-codes) can be used as the property name, but only one property per code, to describe the expected response for that HTTP status code. This field MUST be enclosed in quotation marks (for example, "200") for compatibility between JSON and YAML. To define a range of response codes, this field MAY contain the uppercase wildcard character `X`. For example, `2XX` represents all response codes between `200` and `299`. Only the following range definitions are allowed: `1XX`, `2XX`, `3XX`, `4XX`, and `5XX`. If a response is defined using an explicit code, the explicit code definition takes precedence over the range definition for that code. | -Here is the `id` parameter (without `address`) serialized as `application/json` instead of `text/plain`, and then encoded per RFC1866: +This object MAY be extended with [Specification Extensions](#specification-extensions). -```uri -id=%22f81d4fae-7dec-11d0-a765-00a0c91e6bf6%22 -``` +##### Responses Object Example -###### Example: URL Encoded Form with Binary Values +A 200 response for a successful operation and a default response for others (implying an error): -Note that `application/x-www-form-urlencoded` is a text format, which requires base64-encoding any binary data: +```json +{ + "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" + } + } + } + } +} +``` -```YAML -requestBody: +```yaml +'200': + description: a pet to be returned content: - application/x-www-form-urlencoded: + application/json: schema: - type: object - properties: - name: - type: string - icon: - # The default with "contentEncoding" is application/octet-stream, - # so we need to set image media type(s) in the Encoding Object. - type: string - contentEncoding: base64url - encoding: - icon: - contentType: image/png, image/jpeg -``` - -Given a name of `example` and a solid red 2x2-pixel PNG for `icon`, this -would produce a request body of: - -```uri -name=example&icon=iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAABGdBTUEAALGPC_xhBQAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAAqADAAQAAAABAAAAAgAAAADO0J6QAAAAEElEQVQIHWP8zwACTGCSAQANHQEDqtPptQAAAABJRU5ErkJggg%3D%3D + $ref: '#/components/schemas/Pet' +default: + description: Unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorModel' ``` -Note that the `=` padding characters at the end need to be percent-encoded, even with the "URL safe" `contentEncoding: base64url`. -Some base64-decoding implementations may be able to use the string without the padding per [RFC4648](https://datatracker.ietf.org/doc/html/rfc4648#section-3.2). -However, this is not guaranteed, so it may be more interoperable to keep the padding and rely on percent-decoding. +#### Response Object -##### Encoding `multipart` Media Types +Describes a single response from an API operation, including design-time, static +`links` to operations based on the response. -It is common to use `multipart/form-data` as a `Content-Type` when transferring forms as request bodies. In contrast to OpenAPI 2.0, a `schema` is REQUIRED to define the input parameters to the operation when using `multipart` content. This supports complex structures as well as supporting mechanisms for multiple file uploads. - -The `form-data` disposition and its `name` parameter are mandatory for `multipart/form-data` ([RFC7578](https://www.rfc-editor.org/rfc/rfc7578.html#section-4.2)). -Array properties are handled by applying the same `name` to multiple parts, as is recommended by [RFC7578](https://www.rfc-editor.org/rfc/rfc7578.html#section-4.3) for supplying multiple values per form field. -See [RFC7578](https://www.rfc-editor.org/rfc/rfc7578.html#section-5) for guidance regarding non-ASCII part names. - -Various other `multipart` types, most notable `multipart/mixed` ([RFC2046](https://www.rfc-editor.org/rfc/rfc2046.html#section-5.1.3)) neither require nor forbid specific `Content-Disposition` values, which means care must be taken to ensure that any values used are supported by all relevant software. -It is not currently possible to correlate schema properties with unnamed, ordered parts in media types such as `multipart/mixed`, but implementations MAY choose to support such types when `Content-Disposition: form-data` is used with a `name` parameter. - -Note that there are significant restrictions on what headers can be used with `multipart` media types in general ([RFC2046](https://www.rfc-editor.org/rfc/rfc2046.html#section-5.1)) and `multi-part/form-data` in particular ([RFC7578](https://www.rfc-editor.org/rfc/rfc7578.html#section-4.8)). - -Note also that `Content-Transfer-Encoding` is deprecated for `multipart/form-data` ([RFC7578](https://www.rfc-editor.org/rfc/rfc7578.html#section-4.7)) where binary data is supported, as it is in HTTP. - -+Using `contentEncoding` for a multipart field is equivalent to specifying an [Encoding Object](#encoding-object) with a `headers` field containing `Content-Transfer-Encoding` with a schema that requires the value used in `contentEncoding`. -+If `contentEncoding` is used for a multipart field that has an Encoding Object with a `headers` field containing `Content-Transfer-Encoding` with a schema that disallows the value from `contentEncoding`, the result is undefined for serialization and parsing. - -Note that as stated in [Working with Binary Data](#working-with-binary-data), if the Encoding Object's `contentType`, whether set explicitly or implicitly through its default value rules, disagrees with the `contentMediaType` in a Schema Object, the `contentMediaType` SHALL be ignored. -Because of this, and because the Encoding Object's `contentType` defaulting rules do not take the Schema Object's`contentMediaType` into account, the use of `contentMediaType` with an Encoding Object is NOT RECOMMENDED. - -See [Appendix E](#appendix-e-percent-encoding-and-form-media-types) for a detailed examination of percent-encoding concerns for form media types. - -###### Example: Basic Multipart Form - -When the `encoding` field is _not_ used, the encoding is determined by the Encoding Object's defaults: - -```yaml -requestBody: - content: - multipart/form-data: - schema: - type: object - properties: - id: - # default for primitives without a special format is text/plain - type: string - format: uuid - profileImage: - # default for string with binary format is `application/octet-stream` - type: string - format: binary - addresses: - # default for arrays is based on the type in the `items` - # subschema, which is an object, so `application/json` - type: array - items: - $ref: '#/components/schemas/Address' -``` - -###### Example: Multipart Form with Encoding Objects - -Using `encoding`, we can set more specific types for binary data, or non-JSON formats for complex values. -We can also describe headers for each part: - -```yaml -requestBody: - content: - multipart/form-data: - schema: - type: object - properties: - id: - # default is `text/plain` - type: string - format: uuid - addresses: - # default based on the `items` subschema would be - # `application/json`, but we want these address objects - # serialized as `application/xml` instead - description: addresses in XML format - type: array - items: - $ref: '#/components/schemas/Address' - profileImage: - # default is application/octet-stream, but we can declare - # a more specific image type or types - type: string - format: binary - encoding: - addresses: - # require XML Content-Type in utf-8 encoding - # This is applied to each address part corresponding - # to each address in he array - contentType: application/xml; charset=utf-8 - profileImage: - # only accept png or jpeg - contentType: image/png, image/jpeg - headers: - X-Rate-Limit-Limit: - description: The number of allowed requests in the current period - schema: - type: integer -``` - -###### Example: Multipart Form with Multiple Files - -In accordance with [RFC7578](https://www.rfc-editor.org/rfc/rfc7578.html#section-4.3), multiple files for a single form field are uploaded using the same name (`file` in this example) for each file's part: - -```yaml -requestBody: - content: - multipart/form-data: - schema: - properties: - # The property name 'file' will be used for all files. - file: - type: array - items: {} -``` - -As seen in the [Encoding Object's `contentType` field documentation](#encoding-content-type), the empty schema for `items` indicates a media type of `application/octet-stream`. - -#### Responses Object - -A container for the expected responses of an operation. -The container maps a HTTP response code to the expected response. - -The documentation is not necessarily expected to cover all possible HTTP response codes because they may not be known in advance. -However, documentation is expected to cover a successful operation response and any known errors. - -The `default` MAY be used as a default Response Object for all HTTP codes -that are not covered individually by the Responses Object. - -The Responses Object MUST contain at least one response code, and if only one -response code is provided it SHOULD be the response for a successful operation -call. - -##### Fixed Fields - -| Field Name | Type | Description | -| ---- | :----: | ---- | -| default | [Response Object](#response-object) \| [Reference Object](#reference-object) | The documentation of responses other than the ones declared for specific HTTP response codes. Use this field to cover undeclared responses. | - -##### Patterned Fields - -| Field Pattern | Type | Description | -| ---- | :----: | ---- | -| [HTTP Status Code](#http-status-codes) | [Response Object](#response-object) \| [Reference Object](#reference-object) | Any [HTTP status code](#http-status-codes) can be used as the property name, but only one property per code, to describe the expected response for that HTTP status code. This field MUST be enclosed in quotation marks (for example, "200") for compatibility between JSON and YAML. To define a range of response codes, this field MAY contain the uppercase wildcard character `X`. For example, `2XX` represents all response codes between `200` and `299`. Only the following range definitions are allowed: `1XX`, `2XX`, `3XX`, `4XX`, and `5XX`. If a response is defined using an explicit code, the explicit code definition takes precedence over the range definition for that code. | - -This object MAY be extended with [Specification Extensions](#specification-extensions). - -##### Responses Object Example - -A 200 response for a successful operation and a default response for others (implying an error): - -```json -{ - "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" - } - } - } - } -} -``` - -```yaml -'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 Object - -Describes a single response from an API operation, including design-time, static -`links` to operations based on the response. - -##### Fixed Fields +##### Fixed Fields | Field Name | Type | Description | | ---- | :----: | ---- | @@ -2839,6 +2516,8 @@ JSON Schema implementations MAY choose to treat keywords defined by the OpenAPI This object MAY be extended with [Specification Extensions](#specification-extensions), though as noted, additional properties MAY omit the `x-` prefix within this object. +For additional techniques and examples, see [Schema Modeling Techniques](#schema-modeling-techniques). + ##### Extended Validation with Annotations JSON Schema Draft 2020-12 supports [collecting annotations](https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-00#section-7.7.1), including [treating unrecognized keywords as annotations](https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-00#section-6.5). @@ -2862,48 +2541,6 @@ Even when read-only fields are not required, stripping them is burdensome for cl Note that the behavior of `readOnly` in particular differs from that specified by version 3.0 of this specification. -##### Data Modeling Techniques - -###### Composition and Inheritance (Polymorphism) - -The OpenAPI Specification allows combining and extending model definitions using the `allOf` keyword 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. - -JSON Schema also provides the `anyOf` and `oneOf` keywords, which allow defining multiple schemas where at least one or exactly one of them must be valid, respectively. -As is the case with `allOf`, the schemas are validated _independently_. -These keywords can be used to describe polymorphism, where a single field can accept multiple types of values. - -The OpenAPI specification extends the JSON Schema support for polymorphism by adding the [`discriminator`](#schema-discriminator) field whose value is a [Discriminator Object](#discriminator-object). -When used, the Discriminator Object indicates the name of the property that hints which schema of an `anyOf` or `oneOf` is expected to validate the structure of the model. -The discriminating property MAY be defined as required or optional, but when defined as an optional property the Discriminator Object MUST include a `defaultMapping` field that specifies which schema of the `anyOf` or `oneOf`, or which schema that references the current schema in an `allOf`, is expected to validate the structure of the model when the discriminating property is not present. - -There are two ways to define the value of a discriminating property for an inheriting instance. - -* Use the schema name. -* [Override the schema name](#discriminator-mapping) by overriding the property with a new value. If a new value exists, this takes precedence over the schema name. - -###### Generic (Template) Data Structures - -Implementations MAY support defining generic or template data structures using JSON Schema's dynamic referencing feature: - -* `$dynamicAnchor` identifies a set of possible schemas (including a default placeholder schema) to which a `$dynamicRef` can resolve -* `$dynamicRef` resolves to the first matching `$dynamicAnchor` encountered on its path from the schema entry point to the reference, as described in the JSON Schema specification - -An example is included in the "Schema Object Examples" section below, and further information can be found on the Learn OpenAPI site's ["Dynamic References"](https://learn.openapis.org/referencing/dynamic.html) page. - -###### Annotated Enumerations - -The Schema Object's `enum` keyword does not allow associating descriptions or other information with individual values. - -Implementations MAY support recognizing a `oneOf` or `anyOf` where each subschema in the keyword's array consists of a `const` keyword and annotations such as `title` or `description` as an enumerated type with additional information. The exact behavior of this pattern beyond what is required by JSON Schema is implementation-defined. - -###### XML Modeling - -The [xml](#schema-xml) field allows extra definitions when translating the JSON definition to XML. -The [XML Object](#xml-object) contains additional information about the available options. - ##### Specifying Schema Dialects It is important for tooling to be able to determine which dialect or meta-schema any given resource wishes to be processed with: JSON Schema Core, JSON Schema Validation, OpenAPI Schema dialect, or some custom meta-schema. @@ -2917,6 +2554,8 @@ However, for maximum interoperability, it is RECOMMENDED that OpenAPI descriptio ##### Schema Object Examples +For additional techniques and examples, see [Schema Modeling Techniques](#schema-modeling-techniques). + ###### Primitive Example ```json @@ -3004,35 +2643,6 @@ additionalProperties: $ref: '#/components/schemas/ComplexModel' ``` -###### Model with Annotated Enumeration - -```json -{ - "oneOf": [ - { - "const": "RGB", - "title": "Red, Green, Blue", - "description": "Specify colors with the red, green, and blue additive color model" - }, - { - "const": "CMYK", - "title": "Cyan, Magenta, Yellow, Black", - "description": "Specify colors with the cyan, magenta, yellow, and black subtractive color model" - } - ] -} -``` - -```yaml -oneOf: - - const: RGB - title: Red, Green, Blue - description: Specify colors with the red, green, and blue additive color model - - const: CMYK - title: Cyan, Magenta, Yellow, Black - description: Specify colors with the cyan, magenta, yellow, and black subtractive color model -``` - ###### Model with Example ```json @@ -3072,603 +2682,266 @@ examples: id: 1 ``` -###### Models with Composition +#### Discriminator Object -```json -{ - "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" - } - } - } - ] - } - } - } +When request bodies or response payloads may be one of a number of different schemas, these should use the JSON Schema `anyOf` or `oneOf` keywords to describe the possible schemas (see [Composition and Inheritance](#composition-and-inheritance-polymorphism)). + +A polymorphic schema MAY include a Discriminator Object, which defines the name of the property that may be used as a hint for which schema of the `anyOf` or `oneOf`, or which schema that references the current schema in an `allOf`, is expected to validate the structure of the model. +This hint can be used to aid in serialization, deserialization, and validation. +The Discriminator Object does this by implicitly or explicitly associating the possible values of a named property with alternative schemas. + +Note that `discriminator` MUST NOT change the validation outcome of the schema. + +##### Fixed Fields + +| Field Name | Type | Description | +| ---- | :----: | ---- | +| propertyName | `string` | **REQUIRED**. The name of the discriminating property in the payload that will hold the discriminating value. The discriminating property MAY be defined as required or optional, but when defined as optional the Discriminator Object MUST include a `defaultMapping` field that specifies which schema is expected to validate the structure of the model when the discriminating property is not present. | +| mapping | Map[`string`, `string`] | An object to hold mappings between payload values and schema names or URI references. | +| defaultMapping | `string` | The schema name or URI reference to a schema that is expected to validate the structure of the model when the discriminating property is not present in the payload or contains a value for which there is no explicit or implicit mapping. | + +This object MAY be extended with [Specification Extensions](#specification-extensions). + +##### Conditions for Using the Discriminator Object + +The Discriminator Object is legal only when using one of the composite keywords `oneOf`, `anyOf`, `allOf`. + +In both the `oneOf` and `anyOf` use cases, where those keywords are adjacent to `discriminator`, all possible schemas MUST be listed explicitly. + +To avoid redundancy, the discriminator MAY be added to a parent schema definition, and all schemas building on the parent schema via an `allOf` construct may be used as an alternate schema. + +The `allOf` form of `discriminator` is _only_ useful for non-validation use cases; validation with the parent schema with this form of `discriminator` _does not_ perform a search for child schemas or use them in validation in any way. +This is because `discriminator` cannot change the validation outcome, and no standard JSON Schema keyword connects the parent schema to the child schemas. + +The behavior of any configuration of `oneOf`, `anyOf`, `allOf` and `discriminator` that is not described above is undefined. + +##### Options for Mapping Values to Schemas + +The value of the property named in `propertyName` is used as the name of the associated schema under the [Components Object](#components-object), _unless_ a `mapping` is present for that value. +The `mapping` entry maps a specific property value to either a different schema component name, or to a schema identified by a URI. +When using implicit or explicit schema component names, inline `oneOf` or `anyOf` subschemas are not considered. +The behavior of a `mapping` value or `defaultMapping` value that is both a valid schema name and a valid relative URI reference is implementation-defined, but it is RECOMMENDED that it be treated as a schema name. +To ensure that an ambiguous value (e.g. `"foo"`) is treated as a relative URI reference by all implementations, authors MUST prefix it with the `"."` path segment (e.g. `"./foo"`). + +Mapping keys MUST be string values, but tooling MAY convert response values to strings for comparison. +However, the exact nature of such conversions are implementation-defined. + +##### Optional discriminating property + +When the discriminating property is defined as optional, the [Discriminator Object](#discriminator-object) MUST include a `defaultMapping` field that specifies a schema that is expected to validate the structure of the model when the discriminating property is not present in the payload or contains a value for which there is no explicit or implicit mapping. This allows the schema to still be validated correctly even if the discriminating property is missing. + +The primary use case for an optional discriminating property is to allow a schema to be extended with a discriminator without breaking existing clients that do not provide the discriminating property. + +When the discriminating property is defined as optional, it is important that each subschema that defines a value for the discriminating property also define the property as required, since this is no longer enforced by the parent schema. + +The `defaultMapping` schema is also expected to validate the structure of the model when the discriminating property is present but contains a value for which there is no explicit or implicit mapping. This is typically expressed in the `defaultMapping` schema by excluding any instances with mapped values of the discriminating property, e.g. + +```yaml +OtherPet: + type: object + properties: + petType: + not: + enum: ['cat', 'dog'] +``` + +This prevents the `defaultMapping` schema from validating a payload that includes the discriminating property with a mapped discriminating value, which would cause a validation to fail when polymorphism is described using the `oneOf` JSON schema keyword. + +##### Examples + +For these examples, assume all schemas are in the [entry document](#openapi-description-structure) of the OAD; for handling of `discriminator` in referenced documents see [Resolving Implicit Connections](#resolving-implicit-connections). + +In OAS 3.x, a response payload MAY be described to be exactly one of any number of types: + +```yaml +MyResponseType: + oneOf: + - $ref: '#/components/schemas/Cat' + - $ref: '#/components/schemas/Dog' + - $ref: '#/components/schemas/Lizard' +``` + +which means a valid payload has to match exactly one of the schemas described by `Cat`, `Dog`, or `Lizard`. Deserialization of a `oneOf` can be a costly operation, as it requires determining which schema matches the payload and thus should be used in deserialization. This problem also exists for `anyOf` schemas. A `discriminator` can be used as a "hint" to improve the efficiency of selection of the matching schema. The [Discriminator Object](#discriminator-object) cannot change the validation result of the `oneOf`, it can only help make the deserialization more efficient and provide better error messaging. We can specify the exact field that tells us which schema is expected to match the instance: + +```yaml +MyResponseType: + oneOf: + - $ref: '#/components/schemas/Cat' + - $ref: '#/components/schemas/Dog' + - $ref: '#/components/schemas/Lizard' + discriminator: + propertyName: petType +``` + +The expectation now is that a property with name `petType` _MUST_ be present in the response payload, and the value will correspond to the name of a schema defined in the OpenAPI Description. Thus the response payload: + +```json +{ + "id": 12345, + "petType": "Cat" } ``` +will indicate that the `Cat` schema is expected to match this payload. + +In scenarios where the value of the discriminating property does not match the schema name or implicit mapping is not possible, an optional `mapping` definition can be used: + ```yaml -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 +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: petType + mapping: + dog: '#/components/schemas/Dog' + monster: https://gigantic-server.com/schemas/Monster/schema.json ``` -###### Models with Polymorphism Support +Here the discriminating value of `dog` will map to the schema `#/components/schemas/Dog`, rather than the default (implicit) value of `#/components/schemas/dog`. If the discriminating value does not match an implicit or explicit mapping, no schema can be determined and validation SHOULD fail. -The following example describes a `Pet` model that can represent either a cat or a dog, as distinguished by the `petType` property. Each type of pet has other properties beyond those of the base `Pet` model. An instance without a `petType` property, or with a `petType` property that does not match either `cat` or `dog`, is invalid. +When used in conjunction with the `anyOf` construct, the use of the discriminator can avoid ambiguity for serializers/deserializers where multiple schemas may satisfy a single payload. + +When the discriminating property is defined as optional, the Discriminator Object has to include a `defaultMapping` field that specifies a schema of the `anyOf` or `oneOf` is expected to validate the structure of the model when the discriminating property is not present in the payload. This allows the schema to still be validated correctly even if the discriminator property is missing. + +For example: ```yaml -components: - schemas: - Pet: - type: object - properties: - name: - type: string - required: - - name - - petType - oneOf: - - $ref: '#/components/schemas/Cat' - - $ref: '#/components/schemas/Dog' - Cat: - description: A pet cat - type: object - properties: - petType: - const: 'cat' - huntingSkill: - type: string - description: The measured skill for hunting - enum: - - clueless - - lazy - - adventurous - - aggressive - required: - - huntingSkill - Dog: - description: A pet dog - type: object - properties: - petType: - const: 'dog' - packSize: - type: integer - format: int32 - description: the size of the pack the dog is from - default: 0 - minimum: 0 - required: - - packSize +MyResponseType: + oneOf: + - $ref: '#/components/schemas/Cat' + - $ref: '#/components/schemas/Dog' + - $ref: '#/components/schemas/Lizard' + - $ref: '#/components/schemas/OtherPet' + discriminator: + propertyName: petType + defaultMapping: OtherPet +OtherPet: + type: object + properties: + petType: + not: + enum: ['Cat', 'Dog', 'Lizard'] ``` -###### Models with Polymorphism Support and a Discriminator Object +In this example, if the `petType` property is not present in the payload, or if the value of `petType` is not "Cat", "Dog", or "Lizard", then the payload should validate against the `OtherPet` schema. -The following example extends the example of the previous section by adding a [Discriminator Object](#discriminator-object) to the `Pet` schema. Note that the Discriminator Object is only a hint to the consumer of the API and does not change the validation outcome of the schema. +This example shows the `allOf` usage, which avoids needing to reference all child schemas in the parent: ```yaml components: schemas: Pet: type: object - discriminator: - propertyName: petType - mapping: - cat: '#/components/schemas/Cat' - dog: '#/components/schemas/Dog' - properties: - name: - type: string required: - - name - petType - oneOf: - - $ref: '#/components/schemas/Cat' - - $ref: '#/components/schemas/Dog' - Cat: - description: A pet cat - type: object properties: petType: - const: 'cat' - huntingSkill: type: string - description: The measured skill for hunting - enum: - - clueless - - lazy - - adventurous - - aggressive - required: - - huntingSkill - Dog: - description: A pet dog - type: object - properties: - petType: - const: 'dog' - packSize: - type: integer - format: int32 - description: the size of the pack the dog is from - default: 0 - minimum: 0 - required: - - petType - - packSize -``` - -###### Models with Polymorphism Support using allOf and a Discriminator Object - -It is also possible to describe polymorphic models using `allOf`. The following example uses `allOf` with a [Discriminator Object](#discriminator-object) to describe a polymorphic `Pet` model. - -```yaml -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 discriminating value - description: A representation of a cat + mapping: + dog: Dog + Cat: allOf: - $ref: '#/components/schemas/Pet' - type: object + # all other properties specific to a `Cat` properties: - huntingSkill: + name: type: string - description: The measured skill for hunting - enum: - - clueless - - lazy - - adventurous - - aggressive - required: - - huntingSkill - Dog: # "Dog" will be used as the discriminating value - description: A representation of a dog + Dog: allOf: - $ref: '#/components/schemas/Pet' - type: object + # all other properties specific to a `Dog` properties: - packSize: - type: integer - format: int32 - description: the size of the pack the dog is from - default: 0 - minimum: 0 - required: - - packSize + bark: + type: string + Lizard: + allOf: + - $ref: '#/components/schemas/Pet' + - type: object + # all other properties specific to a `Lizard` + properties: + lovesRocks: + type: boolean ``` -###### Generic Data Structure Model +Validated against the `Pet` schema, a payload like this: -```JSON +```json { - "components": { - "schemas": { - "genericArrayComponent": { - "$id": "fully_generic_array", - "type": "array", - "items": { - "$dynamicRef": "#generic-array" - }, - "$defs": { - "allowAll": { - "$dynamicAnchor": "generic-array" - } - } - }, - "numberArray": { - "$id": "array_of_numbers", - "$ref": "fully_generic_array", - "$defs": { - "numbersOnly": { - "$dynamicAnchor": "generic-array", - "type": "number" - } - } - }, - "stringArray": { - "$id": "array_of_strings", - "$ref": "fully_generic_array", - "$defs": { - "stringsOnly": { - "$dynamicAnchor": "generic-array", - "type": "string" - } - } - }, - "objWithTypedArray": { - "$id": "obj_with_typed_array", - "type": "object", - "required": ["dataType", "data"], - "properties": { - "dataType": { - "enum": ["string", "number"] - } - }, - "oneOf": [{ - "properties": { - "dataType": {"const": "string"}, - "data": {"$ref": "array_of_strings"} - } - }, { - "properties": { - "dataType": {"const": "number"}, - "data": {"$ref": "array_of_numbers"} - } - }] - } - } - } + "petType": "Cat", + "name": "Misty" } ``` -```YAML -components: - schemas: - genericArrayComponent: - $id: fully_generic_array - type: array - items: - $dynamicRef: '#generic-array' - $defs: - allowAll: - $dynamicAnchor: generic-array - numberArray: - $id: array_of_numbers - $ref: fully_generic_array - $defs: - numbersOnly: - $dynamicAnchor: generic-array - type: number - stringArray: - $id: array_of_strings - $ref: fully_generic_array - $defs: - stringsOnly: - $dynamicAnchor: generic-array - type: string - objWithTypedArray: - $id: obj_with_typed_array - type: object - required: - - dataType - - data - properties: - dataType: - enum: - - string - - number - oneOf: - - properties: - dataType: - const: string - data: - $ref: array_of_strings - - properties: - dataType: - const: number - data: - $ref: array_of_numbers +will indicate that the `#/components/schemas/Cat` schema is expected to match. Likewise this payload: + +```json +{ + "petType": "dog", + "bark": "soft" +} ``` -#### Discriminator Object +will map to `#/components/schemas/Dog` because the `dog` entry in the `mapping` element maps to `Dog` which is the schema name for `#/components/schemas/Dog`. -When request bodies or response payloads may be one of a number of different schemas, these should use the JSON Schema `anyOf` or `oneOf` keywords to describe the possible schemas (see [Composition and Inheritance](#composition-and-inheritance-polymorphism)). +#### XML Object -A polymorphic schema MAY include a Discriminator Object, which defines the name of the property that may be used as a hint for which schema of the `anyOf` or `oneOf`, or which schema that references the current schema in an `allOf`, is expected to validate the structure of the model. -This hint can be used to aid in serialization, deserialization, and validation. -The Discriminator Object does this by implicitly or explicitly associating the possible values of a named property with alternative schemas. +A metadata object that allows for more fine-tuned XML model definitions. -Note that `discriminator` MUST NOT change the validation outcome of the schema. +When using arrays, XML element names are _not_ inferred (for singular/plural forms) and the `name` field SHOULD be used to add that information. +See examples for expected behavior. ##### Fixed Fields | Field Name | Type | Description | | ---- | :----: | ---- | -| propertyName | `string` | **REQUIRED**. The name of the discriminating property in the payload that will hold the discriminating value. The discriminating property MAY be defined as required or optional, but when defined as optional the Discriminator Object MUST include a `defaultMapping` field that specifies which schema is expected to validate the structure of the model when the discriminating property is not present. | -| mapping | Map[`string`, `string`] | An object to hold mappings between payload values and schema names or URI references. | -| defaultMapping | `string` | The schema name or URI reference to a schema that is expected to validate the structure of the model when the discriminating property is not present in the payload or contains a value for which there is no explicit or implicit mapping. | +| name | `string` | Replaces the name of the element/attribute used for the described schema property. When defined within `items`, it will affect the name of the individual XML elements within the list. When defined alongside `type` being `"array"` (outside the `items`), it will affect the wrapping element if and only if `wrapped` is `true`. If `wrapped` is `false`, it will be ignored. | +| namespace | `string` | The URI of the namespace definition. Value MUST be in the form of a non-relative URI. | +| prefix | `string` | The prefix to be used for the [name](#xml-name). | +| attribute | `boolean` | Declares whether the property definition translates to an attribute instead of an element. Default value is `false`. | +| wrapped | `boolean` | MAY be used only for an array definition. Signifies whether the array is wrapped (for example, ``) or unwrapped (``). Default value is `false`. The definition takes effect only when defined alongside `type` being `"array"` (outside the `items`). | This object MAY be extended with [Specification Extensions](#specification-extensions). -##### Conditions for Using the Discriminator Object - -The Discriminator Object is legal only when using one of the composite keywords `oneOf`, `anyOf`, `allOf`. - -In both the `oneOf` and `anyOf` use cases, where those keywords are adjacent to `discriminator`, all possible schemas MUST be listed explicitly. - -To avoid redundancy, the discriminator MAY be added to a parent schema definition, and all schemas building on the parent schema via an `allOf` construct may be used as an alternate schema. +The `namespace` field is intended to match the syntax of [XML namespaces](https://www.w3.org/TR/xml-names11/), although there are a few caveats: -The `allOf` form of `discriminator` is _only_ useful for non-validation use cases; validation with the parent schema with this form of `discriminator` _does not_ perform a search for child schemas or use them in validation in any way. -This is because `discriminator` cannot change the validation outcome, and no standard JSON Schema keyword connects the parent schema to the child schemas. +* Versions 3.1.0, 3.0.3, and earlier of this specification erroneously used the term "absolute URI" instead of "non-relative URI", so authors using namespaces that include a fragment should check tooling support carefully. +* XML allows but discourages relative URI-references, while this specification outright forbids them. +* XML 1.1 allows IRIs ([RFC3987](https://datatracker.ietf.org/doc/html/rfc3987)) as namespaces, and specifies that namespaces are compared without any encoding or decoding, which means that IRIs encoded to meet this specification's URI syntax requirement cannot be compared to IRIs as-is. -The behavior of any configuration of `oneOf`, `anyOf`, `allOf` and `discriminator` that is not described above is undefined. +##### XML Object Examples -##### Options for Mapping Values to Schemas +Each of the following examples represent the value of the `properties` keyword in a [Schema Object](#schema-object) that is omitted for brevity. +The JSON and YAML representations of the `properties` value are followed by an example XML representation produced for the single property shown. -The value of the property named in `propertyName` is used as the name of the associated schema under the [Components Object](#components-object), _unless_ a `mapping` is present for that value. -The `mapping` entry maps a specific property value to either a different schema component name, or to a schema identified by a URI. -When using implicit or explicit schema component names, inline `oneOf` or `anyOf` subschemas are not considered. -The behavior of a `mapping` value or `defaultMapping` value that is both a valid schema name and a valid relative URI reference is implementation-defined, but it is RECOMMENDED that it be treated as a schema name. -To ensure that an ambiguous value (e.g. `"foo"`) is treated as a relative URI reference by all implementations, authors MUST prefix it with the `"."` path segment (e.g. `"./foo"`). +###### No XML Element -Mapping keys MUST be string values, but tooling MAY convert response values to strings for comparison. -However, the exact nature of such conversions are implementation-defined. +Basic string property: -##### Optional discriminating property +```json +{ + "animals": { + "type": "string" + } +} +``` -When the discriminating property is defined as optional, the [Discriminator Object](#discriminator-object) MUST include a `defaultMapping` field that specifies a schema that is expected to validate the structure of the model when the discriminating property is not present in the payload or contains a value for which there is no explicit or implicit mapping. This allows the schema to still be validated correctly even if the discriminating property is missing. +```yaml +animals: + type: string +``` -The primary use case for an optional discriminating property is to allow a schema to be extended with a discriminator without breaking existing clients that do not provide the discriminating property. +```xml +... +``` -When the discriminating property is defined as optional, it is important that each subschema that defines a value for the discriminating property also define the property as required, since this is no longer enforced by the parent schema. - -The `defaultMapping` schema is also expected to validate the structure of the model when the discriminating property is present but contains a value for which there is no explicit or implicit mapping. This is typically expressed in the `defaultMapping` schema by excluding any instances with mapped values of the discriminating property, e.g. - -```yaml -OtherPet: - type: object - properties: - petType: - not: - enum: ['cat', 'dog'] -``` - -This prevents the `defaultMapping` schema from validating a payload that includes the discriminating property with a mapped discriminating value, which would cause a validation to fail when polymorphism is described using the `oneOf` JSON schema keyword. - -##### Examples - -For these examples, assume all schemas are in the [entry document](#openapi-description-structure) of the OAD; for handling of `discriminator` in referenced documents see [Resolving Implicit Connections](#resolving-implicit-connections). - -In OAS 3.x, a response payload MAY be described to be exactly one of any number of types: - -```yaml -MyResponseType: - oneOf: - - $ref: '#/components/schemas/Cat' - - $ref: '#/components/schemas/Dog' - - $ref: '#/components/schemas/Lizard' -``` - -which means a valid payload has to match exactly one of the schemas described by `Cat`, `Dog`, or `Lizard`. Deserialization of a `oneOf` can be a costly operation, as it requires determining which schema matches the payload and thus should be used in deserialization. This problem also exists for `anyOf` schemas. A `discriminator` can be used as a "hint" to improve the efficiency of selection of the matching schema. The [Discriminator Object](#discriminator-object) cannot change the validation result of the `oneOf`, it can only help make the deserialization more efficient and provide better error messaging. We can specify the exact field that tells us which schema is expected to match the instance: - -```yaml -MyResponseType: - oneOf: - - $ref: '#/components/schemas/Cat' - - $ref: '#/components/schemas/Dog' - - $ref: '#/components/schemas/Lizard' - discriminator: - propertyName: petType -``` - -The expectation now is that a property with name `petType` _MUST_ be present in the response payload, and the value will correspond to the name of a schema defined in the OpenAPI Description. Thus the response payload: - -```json -{ - "id": 12345, - "petType": "Cat" -} -``` - -will indicate that the `Cat` schema is expected to match this payload. - -In scenarios where the value of the discriminating property does not match the schema name or implicit mapping is not possible, an optional `mapping` definition can be used: - -```yaml -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: petType - mapping: - dog: '#/components/schemas/Dog' - monster: https://gigantic-server.com/schemas/Monster/schema.json -``` - -Here the discriminating value of `dog` will map to the schema `#/components/schemas/Dog`, rather than the default (implicit) value of `#/components/schemas/dog`. If the discriminating value does not match an implicit or explicit mapping, no schema can be determined and validation SHOULD fail. - -When used in conjunction with the `anyOf` construct, the use of the discriminator can avoid ambiguity for serializers/deserializers where multiple schemas may satisfy a single payload. - -When the discriminating property is defined as optional, the Discriminator Object has to include a `defaultMapping` field that specifies a schema of the `anyOf` or `oneOf` is expected to validate the structure of the model when the discriminating property is not present in the payload. This allows the schema to still be validated correctly even if the discriminator property is missing. - -For example: - -```yaml -MyResponseType: - oneOf: - - $ref: '#/components/schemas/Cat' - - $ref: '#/components/schemas/Dog' - - $ref: '#/components/schemas/Lizard' - - $ref: '#/components/schemas/OtherPet' - discriminator: - propertyName: petType - defaultMapping: OtherPet -OtherPet: - type: object - properties: - petType: - not: - enum: ['Cat', 'Dog', 'Lizard'] -``` - -In this example, if the `petType` property is not present in the payload, or if the value of `petType` is not "Cat", "Dog", or "Lizard", then the payload should validate against the `OtherPet` schema. - -This example shows the `allOf` usage, which avoids needing to reference all child schemas in the parent: - -```yaml -components: - schemas: - Pet: - type: object - required: - - petType - properties: - petType: - type: string - discriminator: - propertyName: petType - mapping: - dog: 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 -``` - -Validated against the `Pet` schema, a payload like this: - -```json -{ - "petType": "Cat", - "name": "Misty" -} -``` - -will indicate that the `#/components/schemas/Cat` schema is expected to match. Likewise this payload: - -```json -{ - "petType": "dog", - "bark": "soft" -} -``` - -will map to `#/components/schemas/Dog` because the `dog` entry in the `mapping` element maps to `Dog` which is the schema name for `#/components/schemas/Dog`. - -#### XML Object - -A metadata object that allows for more fine-tuned XML model definitions. - -When using arrays, XML element names are _not_ inferred (for singular/plural forms) and the `name` field SHOULD be used to add that information. -See examples for expected behavior. - -##### Fixed Fields - -| Field Name | Type | Description | -| ---- | :----: | ---- | -| name | `string` | Replaces the name of the element/attribute used for the described schema property. When defined within `items`, it will affect the name of the individual XML elements within the list. When defined alongside `type` being `"array"` (outside the `items`), it will affect the wrapping element if and only if `wrapped` is `true`. If `wrapped` is `false`, it will be ignored. | -| namespace | `string` | The URI of the namespace definition. Value MUST be in the form of a non-relative URI. | -| prefix | `string` | The prefix to be used for the [name](#xml-name). | -| attribute | `boolean` | Declares whether the property definition translates to an attribute instead of an element. Default value is `false`. | -| wrapped | `boolean` | MAY be used only for an array definition. Signifies whether the array is wrapped (for example, ``) or unwrapped (``). Default value is `false`. The definition takes effect only when defined alongside `type` being `"array"` (outside the `items`). | - -This object MAY be extended with [Specification Extensions](#specification-extensions). - -The `namespace` field is intended to match the syntax of [XML namespaces](https://www.w3.org/TR/xml-names11/), although there are a few caveats: - -* Versions 3.1.0, 3.0.3, and earlier of this specification erroneously used the term "absolute URI" instead of "non-relative URI", so authors using namespaces that include a fragment should check tooling support carefully. -* XML allows but discourages relative URI-references, while this specification outright forbids them. -* XML 1.1 allows IRIs ([RFC3987](https://datatracker.ietf.org/doc/html/rfc3987)) as namespaces, and specifies that namespaces are compared without any encoding or decoding, which means that IRIs encoded to meet this specification's URI syntax requirement cannot be compared to IRIs as-is. - -##### XML Object Examples - -Each of the following examples represent the value of the `properties` keyword in a [Schema Object](#schema-object) that is omitted for brevity. -The JSON and YAML representations of the `properties` value are followed by an example XML representation produced for the single property shown. - -###### No XML Element - -Basic string property: - -```json -{ - "animals": { - "type": "string" - } -} -``` - -```yaml -animals: - type: string -``` - -```xml -... -``` - -Basic string array property ([`wrapped`](#xml-wrapped) is `false` by default): +Basic string array property ([`wrapped`](#xml-wrapped) is `false` by default): ```json { @@ -3960,309 +3233,1055 @@ If we change the external element but not the internal ones: } ``` -```yaml -animals: - type: array - items: - type: string - xml: - name: aliens - wrapped: true -``` - -```xml - - value - value - +```yaml +animals: + type: array + items: + type: string + xml: + name: aliens + wrapped: true +``` + +```xml + + value + value + +``` + +#### Security Scheme Object + +Defines a security scheme that can be used by the operations. + +Supported schemes are HTTP authentication, an API key (either as a header, a cookie parameter or as a query parameter), mutual TLS (use of a client certificate), OAuth2's common flows (implicit, password, client credentials and authorization code) as defined in [RFC6749](https://tools.ietf.org/html/rfc6749), OAuth2 device authorization flow as defined in [RFC8628](https://tools.ietf.org/html/rfc8628), and [[OpenID-Connect-Core]]. +Please note that as of 2020, the implicit flow is about to be deprecated by [OAuth 2.0 Security Best Current Practice](https://tools.ietf.org/html/draft-ietf-oauth-security-topics). Recommended for most use cases is Authorization Code Grant flow with PKCE. + +##### Fixed Fields + +| Field Name | Type | Applies To | Description | +| ---- | :----: | ---- | ---- | +| type | `string` | Any | **REQUIRED**. The type of the security scheme. Valid values are `"apiKey"`, `"http"`, `"mutualTLS"`, `"oauth2"`, `"openIdConnect"`. | +| description | `string` | Any | A description for security scheme. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. | +| name | `string` | `apiKey` | **REQUIRED**. The name of the header, query or cookie parameter to be used. | +| in | `string` | `apiKey` | **REQUIRED**. The location of the API key. Valid values are `"query"`, `"header"`, or `"cookie"`. | +| scheme | `string` | `http` | **REQUIRED**. The name of the HTTP Authentication scheme to be used in the [Authorization header as defined in RFC7235](https://tools.ietf.org/html/rfc7235#section-5.1). The values used SHOULD be registered in the [IANA Authentication Scheme registry](https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml). The value is case-insensitive, as defined in [RFC7235](https://datatracker.ietf.org/doc/html/rfc7235#section-2.1). | +| bearerFormat | `string` | `http` (`"bearer"`) | A hint to the client to identify how the bearer token is formatted. Bearer tokens are usually generated by an authorization server, so this information is primarily for documentation purposes. | +| flows | [OAuth Flows Object](#oauth-flows-object) | `oauth2` | **REQUIRED**. An object containing configuration information for the flow types supported. | +| openIdConnectUrl | `string` | `openIdConnect` | **REQUIRED**. [Well-known URL](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig) to discover the [[OpenID-Connect-Discovery]] [provider metadata](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata). | +| oauth2MetadataUrl | `string` | `oauth2` | URL to the oauth2 authorization server metadata [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414). TLS is required. | +| deprecated | `boolean` | Any | Declares this security scheme to be deprecated. Consumers SHOULD refrain from usage of the declared scheme. Default value is `false`. | + +This object MAY be extended with [Specification Extensions](#specification-extensions). + +##### Security Scheme Object Examples + +###### Basic Authentication Example + +```json +{ + "type": "http", + "scheme": "basic" +} +``` + +```yaml +type: http +scheme: basic +``` + +###### API Key Example + +```json +{ + "type": "apiKey", + "name": "api-key", + "in": "header" +} +``` + +```yaml +type: apiKey +name: api-key +in: header +``` + +###### JWT Bearer Example + +```json +{ + "type": "http", + "scheme": "bearer", + "bearerFormat": "JWT" +} +``` + +```yaml +type: http +scheme: bearer +bearerFormat: JWT +``` + +###### MutualTLS Example + +```json +{ + "type": "mutualTLS", + "description": "Cert must be signed by example.com CA" +} +``` + +```yaml +type: mutualTLS +description: Cert must be signed by example.com CA +``` + +###### Implicit OAuth2 Example + +```json +{ + "type": "oauth2", + "flows": { + "implicit": { + "authorizationUrl": "https://example.com/api/oauth/dialog", + "scopes": { + "write:pets": "modify pets in your account", + "read:pets": "read your pets" + } + } + } +} +``` + +```yaml +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 Object + +Allows configuration of the supported OAuth Flows. + +##### Fixed Fields + +| Field Name | Type | Description | +| ---- | :----: | ---- | +| implicit | [OAuth Flow Object](#oauth-flow-object) | Configuration for the OAuth Implicit flow | +| password | [OAuth Flow Object](#oauth-flow-object) | Configuration for the OAuth Resource Owner Password flow | +| clientCredentials | [OAuth Flow Object](#oauth-flow-object) | Configuration for the OAuth Client Credentials flow. Previously called `application` in OpenAPI 2.0. | +| authorizationCode | [OAuth Flow Object](#oauth-flow-object) | Configuration for the OAuth Authorization Code flow. Previously called `accessCode` in OpenAPI 2.0. | +| deviceAuthorization| [OAuth Flow Object](#oauth-flow-object) | Configuration for the OAuth Device Authorization flow. | + +This object MAY be extended with [Specification Extensions](#specification-extensions). + +#### OAuth Flow Object + +Configuration details for a supported OAuth Flow + +##### Fixed Fields + +| Field Name | Type | Applies To | Description | +| ---- | :----: | ---- | ---- | +| authorizationUrl | `string` | `oauth2` (`"implicit"`, `"authorizationCode"`) | **REQUIRED**. The authorization URL to be used for this flow. This MUST be in the form of a URL. The OAuth2 standard requires the use of TLS. | +| deviceAuthorizationUrl | `string` | `oauth2` (`"deviceAuthorization"`) | **REQUIRED**. The device authorization URL to be used for this flow. This MUST be in the form of a URL. The OAuth2 standard requires the use of TLS. | +| tokenUrl | `string` | `oauth2` (`"password"`, `"clientCredentials"`, `"authorizationCode"`, `"deviceAuthorization"`) | **REQUIRED**. The token URL to be used for this flow. This MUST be in the form of a URL. The OAuth2 standard requires the use of TLS. | +| refreshUrl | `string` | `oauth2` | The URL to be used for obtaining refresh tokens. This MUST be in the form of a URL. The OAuth2 standard requires the use of TLS. | +| scopes | Map[`string`, `string`] | `oauth2` | **REQUIRED**. The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. The map MAY be empty. | + +This object MAY be extended with [Specification Extensions](#specification-extensions). + +##### OAuth Flow Object Example + +```JSON +{ + "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" + } + } + } +} +``` + +```yaml +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 Object + +Lists the required security schemes to execute this operation. +The name used for each property MUST correspond to a security scheme declared in the [Security Schemes](#security-scheme-object) under the [Components Object](#components-object). + +A Security Requirement Object MAY refer to multiple security schemes in which case all schemes MUST be satisfied for a request to be authorized. +This enables support for scenarios where multiple query parameters or HTTP headers are required to convey security information. + +When the `security` field is defined on the [OpenAPI Object](#openapi-object) or [Operation Object](#operation-object) and contains multiple Security Requirement Objects, only one of the entries in the list needs to be satisfied to authorize the request. +This enables support for scenarios where the API allows multiple, independent security schemes. + +An empty Security Requirement Object (`{}`) indicates anonymous access is supported. + +##### Patterned Fields + +| Field Pattern | Type | Description | +| ---- | :----: | ---- | +| {name} | [`string`] | Each name MUST correspond to a security scheme which is declared in the [Security Schemes](#security-scheme-object) under the [Components Object](#components-object). If the security scheme is of type `"oauth2"` or `"openIdConnect"`, then the value is a list of scope names required for the execution, and the list MAY be empty if authorization does not require a specified scope. For other security scheme types, the array MAY contain a list of role names which are required for the execution, but are not otherwise defined or exchanged in-band. | + +##### Security Requirement Object Examples + +See also [Appendix F: Resolving Security Requirements in a Referenced Document](#appendix-f-resolving-security-requirements-in-a-referenced-document) for an example using Security Requirement Objects in multi-document OpenAPI Descriptions. + +###### Non-OAuth2 Security Requirement + +```json +{ + "api_key": [] +} +``` + +```yaml +api_key: [] +``` + +###### OAuth2 Security Requirement + +```json +{ + "petstore_auth": ["write:pets", "read:pets"] +} +``` + +```yaml +petstore_auth: + - write:pets + - read:pets +``` + +###### Optional OAuth2 Security + +Optional OAuth2 security as would be defined in an OpenAPI Object or an Operation Object: + +```json +{ + "security": [ + {}, + { + "petstore_auth": ["write:pets", "read:pets"] + } + ] +} +``` + +```yaml +security: + - {} + - petstore_auth: + - write:pets + - read:pets +``` + +### Specification Extensions + +While the OpenAPI Specification tries to accommodate most use cases, additional data can be added to extend the specification at certain points. + +The extensions properties are implemented as patterned fields that are always prefixed by `x-`. + +| Field Pattern | Type | Description | +| ---- | :--: | ---- | +| ^x- | Any | Allows extensions to the OpenAPI Schema. The field name MUST begin with `x-`, for example, `x-internal-id`. Field names beginning `x-oai-` and `x-oas-` are reserved for uses defined by the [OpenAPI Initiative](https://www.openapis.org/). The value can be any valid JSON value (`null`, a primitive, an array, or an object.) | + +The OpenAPI Initiative maintains several [[OpenAPI-Registry|extension registries]], including registries for [individual extension keywords](https://spec.openapis.org/registry/extension/) and [extension keyword namespaces](https://spec.openapis.org/registry/namespace/). + +Extensions are one of the best ways to prove the viability of proposed additions to the specification. +It is therefore RECOMMENDED that implementations be designed for extensibility to support community experimentation. + +Support for any one extension is OPTIONAL, and support for one extension does not imply support for others. + +### 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](#paths-object) MAY be present but 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 would still have access to at least the [Info Object](#info-object) which may contain additional information regarding authentication. +2. The [Path Item Object](#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 from hiding the path itself from the [Paths Object](#paths-object), because the user will be aware of its existence. This allows the documentation provider to finely control what the viewer can see. + +## Modeling Data + +Modeling data in the OpenAPI Specification starts with the [[JSON]] data model of strings, numbers, booleans, arrays, objects, and `null`. +This is further refined and constrained by the [Schema Object](#schema-object), which uses [JSON Schema Draft 2020-12](https://www.ietf.org/archive/id/draft-bhutton-json-schema-01) with several extensions, most notably the [Discriminator Object](#discriminator-object) and the [XML Object](#xml-object). +Several additional Objects determine how to map between in-memory data, which is subject to schema validation, and on-the-wire formats, including the [Parameter Object](#parameter-object), [Header Object](#header-object), [Media Type Object](#media-type-object), and [Encoding Object](#encoding-object). + +This section collects guidance on both the basics of data types, and on how to use these Objects to handle more complex scenarios. + +### Data Types + +Data types in the OAS are based on the types defined by the [JSON Schema Validation Specification Draft 2020-12](https://www.ietf.org/archive/id/draft-bhutton-json-schema-validation-01#section-6.1.1): +"null", "boolean", "object", "array", "number", "string", or "integer". +Models are defined using the [Schema Object](#schema-object), which is a superset of the JSON Schema Specification Draft 2020-12. + +JSON Schema keywords and `format` values operate on JSON "instances" which may be one of the six JSON data types, "null", "boolean", "object", "array", "number", or "string", with certain keywords and formats only applying to a specific type. For example, the `pattern` keyword and the `date-time` format only apply to strings, and treat any instance of the other five types as _automatically valid._ This means JSON Schema keywords and formats do **NOT** implicitly require the expected type. Use the `type` keyword to explicitly constrain the type. + +Note that the `type` keyword allows `"integer"` as a value for convenience, but keyword and format applicability does not recognize integers as being of a distinct JSON type from other numbers because [[RFC7159|JSON]] itself does not make that distinction. Since there is no distinct JSON integer type, JSON Schema defines integers mathematically. This means that both `1` and `1.0` are [equivalent](https://www.ietf.org/archive/id/draft-bhutton-json-schema-00#section-4.2.2), and are both considered to be integers. + +#### Data Type Format + +As defined by the [JSON Schema Validation specification](https://www.ietf.org/archive/id/draft-bhutton-json-schema-validation-01#section-7.3), data types can have an optional modifier keyword: `format`. As described in that specification, `format` is treated as a non-validating annotation by default; the ability to validate `format` varies across implementations. + +The OpenAPI Initiative also hosts a [Format Registry](https://spec.openapis.org/registry/format/) for formats defined by OAS users and other specifications. Support for any registered format is strictly OPTIONAL, and support for one registered format does not imply support for any others. + +Types that are not accompanied by a `format` keyword follow the type definition in the JSON Schema. Tools that do not recognize a specific `format` MAY default back to the `type` alone, as if the `format` is not specified. +For the purpose of [JSON Schema validation](https://www.ietf.org/archive/id/draft-bhutton-json-schema-validation-01#section-7.1), each format should specify the set of JSON data types for which it applies. In this registry, these types are shown in the "JSON Data Type" column. + +The formats defined by the OAS are: + +| `format` | JSON Data Type | Comments | +| ---- | ---- | ---- | +| `int32` | number | signed 32 bits | +| `int64` | number | signed 64 bits (a.k.a long) | +| `float` | number | | +| `double` | number | | +| `password` | string | A hint to obscure the value. | + +As noted under [Data Types](#data-types), both `type: number` and `type: integer` are considered to be numbers in the data model. + +See [Working with Binary Data](#working-with-binary-data) for guidance on modeling binary data in different places and scenarios. +Note that binary data modeling changed between OAS 3.0 and 3.1. + +### Schema Modeling Techniques + +These techniques are all based on the [Schema Object](#schema-object). + +#### Composition and Inheritance (Polymorphism) + +The OpenAPI Specification allows combining and extending model definitions using the `allOf` keyword 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. + +JSON Schema also provides the `anyOf` and `oneOf` keywords, which allow defining multiple schemas where at least one or exactly one of them must be valid, respectively. +As is the case with `allOf`, the schemas are validated _independently_. +These keywords can be used to describe polymorphism, where a single field can accept multiple types of values. + +The OpenAPI specification extends the JSON Schema support for polymorphism by adding the [`discriminator`](#schema-discriminator) field whose value is a [Discriminator Object](#discriminator-object). +When used, the Discriminator Object indicates the name of the property that hints which schema of an `anyOf` or `oneOf` is expected to validate the structure of the model. +The discriminating property MAY be defined as required or optional, but when defined as an optional property the Discriminator Object MUST include a `defaultMapping` field that specifies which schema of the `anyOf` or `oneOf`, or which schema that references the current schema in an `allOf`, is expected to validate the structure of the model when the discriminating property is not present. + +There are two ways to define the value of a discriminating property for an inheriting instance. + +* Use the schema name. +* [Override the schema name](#discriminator-mapping) by overriding the property with a new value. If a new value exists, this takes precedence over the schema name. + +##### Models with Composition + +```json +{ + "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" + } + } + } + ] + } + } + } +} +``` + +```yaml +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 + +The following example describes a `Pet` model that can represent either a cat or a dog, as distinguished by the `petType` property. Each type of pet has other properties beyond those of the base `Pet` model. An instance without a `petType` property, or with a `petType` property that does not match either `cat` or `dog`, is invalid. + +```yaml +components: + schemas: + Pet: + type: object + properties: + name: + type: string + required: + - name + - petType + oneOf: + - $ref: '#/components/schemas/Cat' + - $ref: '#/components/schemas/Dog' + Cat: + description: A pet cat + type: object + properties: + petType: + const: 'cat' + huntingSkill: + type: string + description: The measured skill for hunting + enum: + - clueless + - lazy + - adventurous + - aggressive + required: + - huntingSkill + Dog: + description: A pet dog + type: object + properties: + petType: + const: 'dog' + packSize: + type: integer + format: int32 + description: the size of the pack the dog is from + default: 0 + minimum: 0 + required: + - packSize +``` + +##### Models with Polymorphism Support and a Discriminator Object + +The following example extends the example of the previous section by adding a [Discriminator Object](#discriminator-object) to the `Pet` schema. Note that the Discriminator Object is only a hint to the consumer of the API and does not change the validation outcome of the schema. + +```yaml +components: + schemas: + Pet: + type: object + discriminator: + propertyName: petType + mapping: + cat: '#/components/schemas/Cat' + dog: '#/components/schemas/Dog' + properties: + name: + type: string + required: + - name + - petType + oneOf: + - $ref: '#/components/schemas/Cat' + - $ref: '#/components/schemas/Dog' + Cat: + description: A pet cat + type: object + properties: + petType: + const: 'cat' + huntingSkill: + type: string + description: The measured skill for hunting + enum: + - clueless + - lazy + - adventurous + - aggressive + required: + - huntingSkill + Dog: + description: A pet dog + type: object + properties: + petType: + const: 'dog' + packSize: + type: integer + format: int32 + description: the size of the pack the dog is from + default: 0 + minimum: 0 + required: + - petType + - packSize +``` + +##### Models with Polymorphism Support using allOf and a Discriminator Object + +It is also possible to describe polymorphic models using `allOf`. The following example uses `allOf` with a [Discriminator Object](#discriminator-object) to describe a polymorphic `Pet` model. + +```yaml +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 discriminating 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 discriminating 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 +``` + +#### Generic (Template) Data Structures + +Implementations MAY support defining generic or template data structures using JSON Schema's dynamic referencing feature: + +* `$dynamicAnchor` identifies a set of possible schemas (including a default placeholder schema) to which a `$dynamicRef` can resolve +* `$dynamicRef` resolves to the first matching `$dynamicAnchor` encountered on its path from the schema entry point to the reference, as described in the JSON Schema specification + +An example is included in the "Schema Object Examples" section below, and further information can be found on the Learn OpenAPI site's ["Dynamic References"](https://learn.openapis.org/referencing/dynamic.html) page. + +##### Generic Data Structure Model + +```JSON +{ + "components": { + "schemas": { + "genericArrayComponent": { + "$id": "fully_generic_array", + "type": "array", + "items": { + "$dynamicRef": "#generic-array" + }, + "$defs": { + "allowAll": { + "$dynamicAnchor": "generic-array" + } + } + }, + "numberArray": { + "$id": "array_of_numbers", + "$ref": "fully_generic_array", + "$defs": { + "numbersOnly": { + "$dynamicAnchor": "generic-array", + "type": "number" + } + } + }, + "stringArray": { + "$id": "array_of_strings", + "$ref": "fully_generic_array", + "$defs": { + "stringsOnly": { + "$dynamicAnchor": "generic-array", + "type": "string" + } + } + }, + "objWithTypedArray": { + "$id": "obj_with_typed_array", + "type": "object", + "required": ["dataType", "data"], + "properties": { + "dataType": { + "enum": ["string", "number"] + } + }, + "oneOf": [{ + "properties": { + "dataType": {"const": "string"}, + "data": {"$ref": "array_of_strings"} + } + }, { + "properties": { + "dataType": {"const": "number"}, + "data": {"$ref": "array_of_numbers"} + } + }] + } + } + } +} +``` + +```YAML +components: + schemas: + genericArrayComponent: + $id: fully_generic_array + type: array + items: + $dynamicRef: '#generic-array' + $defs: + allowAll: + $dynamicAnchor: generic-array + numberArray: + $id: array_of_numbers + $ref: fully_generic_array + $defs: + numbersOnly: + $dynamicAnchor: generic-array + type: number + stringArray: + $id: array_of_strings + $ref: fully_generic_array + $defs: + stringsOnly: + $dynamicAnchor: generic-array + type: string + objWithTypedArray: + $id: obj_with_typed_array + type: object + required: + - dataType + - data + properties: + dataType: + enum: + - string + - number + oneOf: + - properties: + dataType: + const: string + data: + $ref: array_of_strings + - properties: + dataType: + const: number + data: + $ref: array_of_numbers ``` -#### Security Scheme Object - -Defines a security scheme that can be used by the operations. - -Supported schemes are HTTP authentication, an API key (either as a header, a cookie parameter or as a query parameter), mutual TLS (use of a client certificate), OAuth2's common flows (implicit, password, client credentials and authorization code) as defined in [RFC6749](https://tools.ietf.org/html/rfc6749), OAuth2 device authorization flow as defined in [RFC8628](https://tools.ietf.org/html/rfc8628), and [[OpenID-Connect-Core]]. -Please note that as of 2020, the implicit flow is about to be deprecated by [OAuth 2.0 Security Best Current Practice](https://tools.ietf.org/html/draft-ietf-oauth-security-topics). Recommended for most use cases is Authorization Code Grant flow with PKCE. - -##### Fixed Fields - -| Field Name | Type | Applies To | Description | -| ---- | :----: | ---- | ---- | -| type | `string` | Any | **REQUIRED**. The type of the security scheme. Valid values are `"apiKey"`, `"http"`, `"mutualTLS"`, `"oauth2"`, `"openIdConnect"`. | -| description | `string` | Any | A description for security scheme. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. | -| name | `string` | `apiKey` | **REQUIRED**. The name of the header, query or cookie parameter to be used. | -| in | `string` | `apiKey` | **REQUIRED**. The location of the API key. Valid values are `"query"`, `"header"`, or `"cookie"`. | -| scheme | `string` | `http` | **REQUIRED**. The name of the HTTP Authentication scheme to be used in the [Authorization header as defined in RFC7235](https://tools.ietf.org/html/rfc7235#section-5.1). The values used SHOULD be registered in the [IANA Authentication Scheme registry](https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml). The value is case-insensitive, as defined in [RFC7235](https://datatracker.ietf.org/doc/html/rfc7235#section-2.1). | -| bearerFormat | `string` | `http` (`"bearer"`) | A hint to the client to identify how the bearer token is formatted. Bearer tokens are usually generated by an authorization server, so this information is primarily for documentation purposes. | -| flows | [OAuth Flows Object](#oauth-flows-object) | `oauth2` | **REQUIRED**. An object containing configuration information for the flow types supported. | -| openIdConnectUrl | `string` | `openIdConnect` | **REQUIRED**. [Well-known URL](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig) to discover the [[OpenID-Connect-Discovery]] [provider metadata](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata). | -| oauth2MetadataUrl | `string` | `oauth2` | URL to the oauth2 authorization server metadata [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414). TLS is required. | -| deprecated | `boolean` | Any | Declares this security scheme to be deprecated. Consumers SHOULD refrain from usage of the declared scheme. Default value is `false`. | +#### Annotated Enumerations -This object MAY be extended with [Specification Extensions](#specification-extensions). +The Schema Object's `enum` keyword does not allow associating descriptions or other information with individual values. -##### Security Scheme Object Examples +Implementations MAY support recognizing a `oneOf` or `anyOf` where each subschema in the keyword's array consists of a `const` keyword and annotations such as `title` or `description` as an enumerated type with additional information. The exact behavior of this pattern beyond what is required by JSON Schema is implementation-defined. -###### Basic Authentication Example +##### Model with Annotated Enumeration ```json { - "type": "http", - "scheme": "basic" + "oneOf": [ + { + "const": "RGB", + "title": "Red, Green, Blue", + "description": "Specify colors with the red, green, and blue additive color model" + }, + { + "const": "CMYK", + "title": "Cyan, Magenta, Yellow, Black", + "description": "Specify colors with the cyan, magenta, yellow, and black subtractive color model" + } + ] } ``` ```yaml -type: http -scheme: basic +oneOf: + - const: RGB + title: Red, Green, Blue + description: Specify colors with the red, green, and blue additive color model + - const: CMYK + title: Cyan, Magenta, Yellow, Black + description: Specify colors with the cyan, magenta, yellow, and black subtractive color model ``` -###### API Key Example +### Modeling Non-JSON Data -```json -{ - "type": "apiKey", - "name": "api-key", - "in": "header" -} -``` +This section describes how to model non-JSON formats, either by mapping the format into the +[JSON Schema data model](https://www.ietf.org/archive/id/draft-bhutton-json-schema-01.html#name-instance-data-model) +or by using additional Objects such as the [Encoding Object](#encoding-object). -```yaml -type: apiKey -name: api-key -in: header -``` +#### XML Modeling -###### JWT Bearer Example +The [xml](#schema-xml) field in the [Schema Object](#schema-object) allows extra definitions when translating the JSON definition to XML. +The [XML Object](#xml-object) contains additional information about the available options. -```json -{ - "type": "http", - "scheme": "bearer", - "bearerFormat": "JWT" -} -``` +#### Working with Binary Data -```yaml -type: http -scheme: bearer -bearerFormat: JWT -``` +The OAS can describe either _raw_ or _encoded_ binary data. -###### MutualTLS Example +* **raw binary** is used where unencoded binary data is allowed, such as when sending a binary payload as the entire HTTP message body, or as part of a `multipart/*` payload that allows binary parts +* **encoded binary** is used where binary data is embedded in a text-only format such as `application/json` or `application/x-www-form-urlencoded` (either as a message body or in the URL query string). -```json -{ - "type": "mutualTLS", - "description": "Cert must be signed by example.com CA" -} -``` +In the following table showing how to use Schema Object keywords for binary data, we use `image/png` as an example binary media type. Any binary media type, including `application/octet-stream`, is sufficient to indicate binary content. -```yaml -type: mutualTLS -description: Cert must be signed by example.com CA -``` +| Keyword | Raw | Encoded | Comments | +| ---- | ---- | ---- | ---- | +| `type` | _omit_ | `string` | raw binary is [outside of `type`](https://www.ietf.org/archive/id/draft-bhutton-json-schema-01#section-4.2.3) | +| `contentMediaType` | `image/png` | `image/png` | can sometimes be omitted if redundant (see below) | +| `contentEncoding` | _omit_ | `base64` or `base64url` | other encodings are [allowed](https://www.ietf.org/archive/id/draft-bhutton-json-schema-validation-01#section-8.3) | -###### Implicit OAuth2 Example +Note that the encoding indicated by `contentEncoding`, which inflates the size of data in order to represent it as 7-bit ASCII text, is unrelated to HTTP's `Content-Encoding` header, which indicates whether and how a message body has been compressed and is applied after all content serialization described in this section has occurred. Since HTTP allows unencoded binary message bodies, there is no standardized HTTP header for indicating base64 or similar encoding of an entire message body. -```json -{ - "type": "oauth2", - "flows": { - "implicit": { - "authorizationUrl": "https://example.com/api/oauth/dialog", - "scopes": { - "write:pets": "modify pets in your account", - "read:pets": "read your pets" - } - } - } -} -``` +Using a `contentEncoding` of `base64url` ensures that URL encoding (as required in the query string and in message bodies of type `application/x-www-form-urlencoded`) does not need to further encode any part of the already-encoded binary data. -```yaml -type: oauth2 -flows: - implicit: - authorizationUrl: https://example.com/api/oauth/dialog - scopes: - write:pets: modify pets in your account - read:pets: read your pets -``` +The `contentMediaType` keyword is redundant if the media type is already set: -#### OAuth Flows Object +* as the key for a [MediaType Object](#media-type-object) +* in the `contentType` field of an [Encoding Object](#encoding-object) -Allows configuration of the supported OAuth Flows. +If the [Schema Object](#schema-object) will be processed by a non-OAS-aware JSON Schema implementation, it may be useful to include `contentMediaType` even if it is redundant. However, if `contentMediaType` contradicts a relevant Media Type Object or Encoding Object, then `contentMediaType` SHALL be ignored. -##### Fixed Fields +The `maxLength` keyword MAY be used to set an expected upper bound on the length of a streaming payload. The keyword can be applied to either string data, including encoded binary data, or to unencoded binary data. For unencoded binary, the length is the number of octets. -| Field Name | Type | Description | -| ---- | :----: | ---- | -| implicit | [OAuth Flow Object](#oauth-flow-object) | Configuration for the OAuth Implicit flow | -| password | [OAuth Flow Object](#oauth-flow-object) | Configuration for the OAuth Resource Owner Password flow | -| clientCredentials | [OAuth Flow Object](#oauth-flow-object) | Configuration for the OAuth Client Credentials flow. Previously called `application` in OpenAPI 2.0. | -| authorizationCode | [OAuth Flow Object](#oauth-flow-object) | Configuration for the OAuth Authorization Code flow. Previously called `accessCode` in OpenAPI 2.0. | -| deviceAuthorization| [OAuth Flow Object](#oauth-flow-object) | Configuration for the OAuth Device Authorization flow. | +##### Migrating binary descriptions from OAS 3.0 -This object MAY be extended with [Specification Extensions](#specification-extensions). +The following table shows how to migrate from OAS 3.0 binary data descriptions, continuing to use `image/png` as the example binary media type: -#### OAuth Flow Object +| OAS < 3.1 | OAS >= 3.1 | Comments | +| ---- | ---- | ---- | +| type: string
format: binary | contentMediaType: image/png | if redundant, can be omitted, often resulting in an empty [Schema Object](#schema-object) | +| type: string
format: byte | type: string
contentMediaType: image/png
contentEncoding: base64 | note that `base64url` can be used to avoid re-encoding the base64 string to be URL-safe | -Configuration details for a supported OAuth Flow +#### Considerations for File Uploads -##### Fixed Fields +In contrast to OpenAPI 2.0, `file` input/output content in OAS 3.x is described with the same semantics as any other schema type. -| Field Name | Type | Applies To | Description | -| ---- | :----: | ---- | ---- | -| authorizationUrl | `string` | `oauth2` (`"implicit"`, `"authorizationCode"`) | **REQUIRED**. The authorization URL to be used for this flow. This MUST be in the form of a URL. The OAuth2 standard requires the use of TLS. | -| deviceAuthorizationUrl | `string` | `oauth2` (`"deviceAuthorization"`) | **REQUIRED**. The device authorization URL to be used for this flow. This MUST be in the form of a URL. The OAuth2 standard requires the use of TLS. | -| tokenUrl | `string` | `oauth2` (`"password"`, `"clientCredentials"`, `"authorizationCode"`, `"deviceAuthorization"`) | **REQUIRED**. The token URL to be used for this flow. This MUST be in the form of a URL. The OAuth2 standard requires the use of TLS. | -| refreshUrl | `string` | `oauth2` | The URL to be used for obtaining refresh tokens. This MUST be in the form of a URL. The OAuth2 standard requires the use of TLS. | -| scopes | Map[`string`, `string`] | `oauth2` | **REQUIRED**. The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. The map MAY be empty. | +In contrast to OAS 3.0, the `format` keyword has no effect on the content-encoding of the schema in OAS 3.1. Instead, JSON Schema's `contentEncoding` and `contentMediaType` keywords are used. See [Working With Binary Data](#working-with-binary-data) for how to model various scenarios with these keywords, and how to migrate from the previous `format` usage. -This object MAY be extended with [Specification Extensions](#specification-extensions). +Examples: -##### OAuth Flow Object Example +Content transferred in binary (octet-stream) MAY omit `schema`: -```JSON -{ - "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" - } - } - } -} +```yaml +# a PNG image as a binary file: +content: + image/png: {} +``` + +```yaml +# an arbitrary binary file: +content: + application/octet-stream: {} ``` ```yaml -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 +# arbitrary JSON without constraints beyond being syntactically valid: +content: + application/json: {} ``` -#### Security Requirement Object +These examples apply to either input payloads of file uploads or response payloads. -Lists the required security schemes to execute this operation. -The name used for each property MUST correspond to a security scheme declared in the [Security Schemes](#security-scheme-object) under the [Components Object](#components-object). +A `requestBody` for submitting a file in a `POST` operation may look like the following example: -A Security Requirement Object MAY refer to multiple security schemes in which case all schemes MUST be satisfied for a request to be authorized. -This enables support for scenarios where multiple query parameters or HTTP headers are required to convey security information. +```yaml +requestBody: + content: + application/octet-stream: {} +``` -When the `security` field is defined on the [OpenAPI Object](#openapi-object) or [Operation Object](#operation-object) and contains multiple Security Requirement Objects, only one of the entries in the list needs to be satisfied to authorize the request. -This enables support for scenarios where the API allows multiple, independent security schemes. +In addition, specific media types MAY be specified: -An empty Security Requirement Object (`{}`) indicates anonymous access is supported. +```yaml +# multiple, specific media types may be specified: +requestBody: + content: + # a binary file of type png or jpeg + image/jpeg: {} + image/png: {} +``` -##### Patterned Fields +To upload multiple files, a `multipart` media type MUST be used as shown under [Example: Multipart Form with Multiple Files](#example-multipart-form-with-multiple-files). -| Field Pattern | Type | Description | -| ---- | :----: | ---- | -| {name} | [`string`] | Each name MUST correspond to a security scheme which is declared in the [Security Schemes](#security-scheme-object) under the [Components Object](#components-object). If the security scheme is of type `"oauth2"` or `"openIdConnect"`, then the value is a list of scope names required for the execution, and the list MAY be empty if authorization does not require a specified scope. For other security scheme types, the array MAY contain a list of role names which are required for the execution, but are not otherwise defined or exchanged in-band. | +#### Encoding the `x-www-form-urlencoded` Media Type -##### Security Requirement Object Examples +To submit content using form url encoding via [RFC1866](https://tools.ietf.org/html/rfc1866), use the `application/x-www-form-urlencoded` media type in the [Media Type Object](#media-type-object) under the [Request Body Object](#request-body-object). +This configuration means that the request body MUST be encoded per [RFC1866](https://tools.ietf.org/html/rfc1866) when passed to the server, after any complex objects have been serialized to a string representation. -See also [Appendix F: Resolving Security Requirements in a Referenced Document](#appendix-f-resolving-security-requirements-in-a-referenced-document) for an example using Security Requirement Objects in multi-document OpenAPI Descriptions. +See [Appendix E](#appendix-e-percent-encoding-and-form-media-types) for a detailed examination of percent-encoding concerns for form media types. -###### Non-OAuth2 Security Requirement +##### Example: URL Encoded Form with JSON Values -```json -{ - "api_key": [] -} -``` +When there is no [`encoding`](#media-type-encoding) field, the serialization strategy is based on the Encoding Object's default values: ```yaml -api_key: [] +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: {} ``` -###### OAuth2 Security Requirement +With this example, consider an `id` of `f81d4fae-7dec-11d0-a765-00a0c91e6bf6` and a US-style address (with ZIP+4) as follows: ```json { - "petstore_auth": ["write:pets", "read:pets"] + "streetAddress": "123 Example Dr.", + "city": "Somewhere", + "state": "CA", + "zip": "99999+1234" } ``` -```yaml -petstore_auth: - - write:pets - - read:pets +Assuming the most compact representation of the JSON value (with unnecessary whitespace removed), we would expect to see the following request body, where space characters have been replaced with `+` and `+`, `"`, `{`, and `}` have been percent-encoded to `%2B`, `%22`, `%7B`, and `%7D`, respectively: + +```uri +id=f81d4fae-7dec-11d0-a765-00a0c91e6bf6&address=%7B%22streetAddress%22:%22123+Example+Dr.%22,%22city%22:%22Somewhere%22,%22state%22:%22CA%22,%22zip%22:%2299999%2B1234%22%7D ``` -###### Optional OAuth2 Security +Note that the `id` keyword is treated as `text/plain` per the [Encoding Object](#encoding-object)'s default behavior, and is serialized as-is. +If it were treated as `application/json`, then the serialized value would be a JSON string including quotation marks, which would be percent-encoded as `%22`. -Optional OAuth2 security as would be defined in an OpenAPI Object or an Operation Object: +Here is the `id` parameter (without `address`) serialized as `application/json` instead of `text/plain`, and then encoded per RFC1866: -```json -{ - "security": [ - {}, - { - "petstore_auth": ["write:pets", "read:pets"] - } - ] -} +```uri +id=%22f81d4fae-7dec-11d0-a765-00a0c91e6bf6%22 ``` -```yaml -security: - - {} - - petstore_auth: - - write:pets - - read:pets +##### Example: URL Encoded Form with Binary Values + +Note that `application/x-www-form-urlencoded` is a text format, which requires base64-encoding any binary data: + +```YAML +requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + properties: + name: + type: string + icon: + # The default with "contentEncoding" is application/octet-stream, + # so we need to set image media type(s) in the Encoding Object. + type: string + contentEncoding: base64url + encoding: + icon: + contentType: image/png, image/jpeg ``` -### Specification Extensions +Given a name of `example` and a solid red 2x2-pixel PNG for `icon`, this +would produce a request body of: -While the OpenAPI Specification tries to accommodate most use cases, additional data can be added to extend the specification at certain points. +```uri +name=example&icon=iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAABGdBTUEAALGPC_xhBQAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAAqADAAQAAAABAAAAAgAAAADO0J6QAAAAEElEQVQIHWP8zwACTGCSAQANHQEDqtPptQAAAABJRU5ErkJggg%3D%3D +``` -The extensions properties are implemented as patterned fields that are always prefixed by `x-`. +Note that the `=` padding characters at the end need to be percent-encoded, even with the "URL safe" `contentEncoding: base64url`. +Some base64-decoding implementations may be able to use the string without the padding per [RFC4648](https://datatracker.ietf.org/doc/html/rfc4648#section-3.2). +However, this is not guaranteed, so it may be more interoperable to keep the padding and rely on percent-decoding. -| Field Pattern | Type | Description | -| ---- | :--: | ---- | -| ^x- | Any | Allows extensions to the OpenAPI Schema. The field name MUST begin with `x-`, for example, `x-internal-id`. Field names beginning `x-oai-` and `x-oas-` are reserved for uses defined by the [OpenAPI Initiative](https://www.openapis.org/). The value can be any valid JSON value (`null`, a primitive, an array, or an object.) | +#### Encoding `multipart` Media Types -The OpenAPI Initiative maintains several [[OpenAPI-Registry|extension registries]], including registries for [individual extension keywords](https://spec.openapis.org/registry/extension/) and [extension keyword namespaces](https://spec.openapis.org/registry/namespace/). +It is common to use `multipart/form-data` as a `Content-Type` when transferring forms as request bodies. In contrast to OpenAPI 2.0, a `schema` is REQUIRED to define the input parameters to the operation when using `multipart` content. This supports complex structures as well as supporting mechanisms for multiple file uploads. -Extensions are one of the best ways to prove the viability of proposed additions to the specification. -It is therefore RECOMMENDED that implementations be designed for extensibility to support community experimentation. +The `form-data` disposition and its `name` parameter are mandatory for `multipart/form-data` ([RFC7578](https://www.rfc-editor.org/rfc/rfc7578.html#section-4.2)). +Array properties are handled by applying the same `name` to multiple parts, as is recommended by [RFC7578](https://www.rfc-editor.org/rfc/rfc7578.html#section-4.3) for supplying multiple values per form field. +See [RFC7578](https://www.rfc-editor.org/rfc/rfc7578.html#section-5) for guidance regarding non-ASCII part names. -Support for any one extension is OPTIONAL, and support for one extension does not imply support for others. +Various other `multipart` types, most notable `multipart/mixed` ([RFC2046](https://www.rfc-editor.org/rfc/rfc2046.html#section-5.1.3)) neither require nor forbid specific `Content-Disposition` values, which means care must be taken to ensure that any values used are supported by all relevant software. +It is not currently possible to correlate schema properties with unnamed, ordered parts in media types such as `multipart/mixed`, but implementations MAY choose to support such types when `Content-Disposition: form-data` is used with a `name` parameter. -### Security Filtering +Note that there are significant restrictions on what headers can be used with `multipart` media types in general ([RFC2046](https://www.rfc-editor.org/rfc/rfc2046.html#section-5.1)) and `multi-part/form-data` in particular ([RFC7578](https://www.rfc-editor.org/rfc/rfc7578.html#section-4.8)). -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. +Note also that `Content-Transfer-Encoding` is deprecated for `multipart/form-data` ([RFC7578](https://www.rfc-editor.org/rfc/rfc7578.html#section-4.7)) where binary data is supported, as it is in HTTP. -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. ++Using `contentEncoding` for a multipart field is equivalent to specifying an [Encoding Object](#encoding-object) with a `headers` field containing `Content-Transfer-Encoding` with a schema that requires the value used in `contentEncoding`. ++If `contentEncoding` is used for a multipart field that has an Encoding Object with a `headers` field containing `Content-Transfer-Encoding` with a schema that disallows the value from `contentEncoding`, the result is undefined for serialization and parsing. -Two examples of this: +Note that as stated in [Working with Binary Data](#working-with-binary-data), if the Encoding Object's `contentType`, whether set explicitly or implicitly through its default value rules, disagrees with the `contentMediaType` in a Schema Object, the `contentMediaType` SHALL be ignored. +Because of this, and because the Encoding Object's `contentType` defaulting rules do not take the Schema Object's`contentMediaType` into account, the use of `contentMediaType` with an Encoding Object is NOT RECOMMENDED. -1. The [Paths Object](#paths-object) MAY be present but 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 would still have access to at least the [Info Object](#info-object) which may contain additional information regarding authentication. -2. The [Path Item Object](#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 from hiding the path itself from the [Paths Object](#paths-object), because the user will be aware of its existence. This allows the documentation provider to finely control what the viewer can see. +See [Appendix E](#appendix-e-percent-encoding-and-form-media-types) for a detailed examination of percent-encoding concerns for form media types. + +##### Example: Basic Multipart Form + +When the `encoding` field is _not_ used, the encoding is determined by the Encoding Object's defaults: + +```yaml +requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + id: + # default for primitives without a special format is text/plain + type: string + format: uuid + profileImage: + # default for string with binary format is `application/octet-stream` + type: string + format: binary + addresses: + # default for arrays is based on the type in the `items` + # subschema, which is an object, so `application/json` + type: array + items: + $ref: '#/components/schemas/Address' +``` + +##### Example: Multipart Form with Encoding Objects + +Using `encoding`, we can set more specific types for binary data, or non-JSON formats for complex values. +We can also describe headers for each part: + +```yaml +requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + id: + # default is `text/plain` + type: string + format: uuid + addresses: + # default based on the `items` subschema would be + # `application/json`, but we want these address objects + # serialized as `application/xml` instead + description: addresses in XML format + type: array + items: + $ref: '#/components/schemas/Address' + profileImage: + # default is application/octet-stream, but we can declare + # a more specific image type or types + type: string + format: binary + encoding: + addresses: + # require XML Content-Type in utf-8 encoding + # This is applied to each address part corresponding + # to each address in he array + contentType: application/xml; charset=utf-8 + profileImage: + # only accept png or jpeg + contentType: image/png, image/jpeg + headers: + X-Rate-Limit-Limit: + description: The number of allowed requests in the current period + schema: + type: integer +``` + +##### Example: Multipart Form with Multiple Files + +In accordance with [RFC7578](https://www.rfc-editor.org/rfc/rfc7578.html#section-4.3), multiple files for a single form field are uploaded using the same name (`file` in this example) for each file's part: + +```yaml +requestBody: + content: + multipart/form-data: + schema: + properties: + # The property name 'file' will be used for all files. + file: + type: array + items: {} +``` + +As seen in the [Encoding Object's `contentType` field documentation](#encoding-content-type), the empty schema for `items` indicates a media type of `application/octet-stream`. ## Security Considerations