diff --git a/versions/3.0.4.md b/versions/3.0.4.md
index 3918dc0784..1f025cd897 100644
--- a/versions/3.0.4.md
+++ b/versions/3.0.4.md
@@ -1465,10 +1465,10 @@ See [Working With Examples](#working-with-examples) for further guidance regardi
##### Fixed Fields
Field Name | Type | Description
---|:---:|---
-schema | [Schema Object](#schemaObject) \| [Reference Object](#referenceObject) | The schema defining the content of the request, response, or parameter.
+schema | [Schema Object](#schemaObject) \| [Reference Object](#referenceObject) | The schema defining the content of the request, response, parameter, or header.
example | Any | Example of the media type; see [Working With Examples](#working-with-examples).
examples | Map[ `string`, [Example Object](#exampleObject) \| [Reference Object](#referenceObject)] | Examples of the media type; see [Working With Examples](#working-with-examples).
-encoding | Map[`string`, [Encoding Object](#encodingObject)] | A map between a property name and its encoding information. The key, being the property name, MUST exist in the schema as a property. The encoding attribute SHALL only apply to [Request Body Objects](#requestBodyObject), and only when the media type is `multipart` or `application/x-www-form-urlencoded`. If no Encoding Object is provided for a property, the behavior is determined by the default values documented for the Encoding Object.
+encoding | Map[`string`, [Encoding Object](#encodingObject)] | A map between a property name and information providing more control over the serialization of the value. The key, being the property name, MUST exist in the schema as a property. The encoding attribute SHALL only apply to [Request Body Objects](#requestBodyObject), and only when the media type is `multipart` or `application/x-www-form-urlencoded`. If no Encoding Object is provided for a property, the behavior is determined by the default values documented for the Encoding Object.
This object MAY be extended with [Specification Extensions](#specificationExtensions).
@@ -1576,121 +1576,15 @@ requestBody:
format: binary
```
-To upload multiple files, a `multipart` media type MUST be used:
-
-```yaml
-requestBody:
- content:
- multipart/form-data:
- schema:
- properties:
- # The property name 'file' will be used for all files.
- file:
- type: array
- items:
- type: string
- format: binary
-
-```
+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
-To submit content using form url encoding via [RFC1866](https://tools.ietf.org/html/rfc1866), the following
-definition may be used:
-
-```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: {}
-```
-
-In this example, the contents in the `requestBody` MUST be encoded per [RFC1866](https://tools.ietf.org/html/rfc1866) when passed to the server. In addition, the `address` field complex object will be serialized to a string representation prior to encoding.
-
-When passing complex objects in the `application/x-www-form-urlencoded` content type, the default serialization strategy of such properties is described in the [Encoding Object](#encodingObject)'s [`style`](#encodingStyle) property as `form`.
-
-With this example, given an `id` of `f81d4fae-7dec-11d0-a765-00a0c91e6bf6` and a US-style address (with ZIP+4) as follows:
-
-```json
-{
- "streetAddress": "123 Example Dr.",
- "city": "Somewhere",
- "state": "CA",
- "zip": "99999+1234"
-}
-```
-
-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:
-
-```urlencoded
-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
-```
-
-Note that the `id` keyword is treated as `text/plain` per the [Encoding Object](#encodingObject)'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`.
-
-Here is the `id` parameter (without `address`) serialized as `application/json` instead of `text/plain`, and then encoded per RFC1866:
-
-```urlencoded
-id=%22f81d4fae-7dec-11d0-a765-00a0c91e6bf6%22
-```
-
-See [Appendix E](#percentEncodingAndFormMediaTypes) for a detailed examination of percent-encoding concerns for form media types.
+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` attribute.
##### Special Considerations for `multipart` Content
-It is common to use `multipart/form-data` as a `Content-Type` when transferring request bodies to operations. In contrast to 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.
-
-When passing in `multipart` types, boundaries MAY be used to separate sections of the content being transferred — thus, the following default `Content-Type`s are defined for `multipart`:
-
-* If the property is a primitive, or an array of primitive values, the default Content-Type is `text/plain`
-* If the property is complex, or an array of complex values, the default Content-Type is `application/json`
-* If the property is a `type: string` with `format: binary` or `format: byte` (aka a file object), the default Content-Type is `application/octet-stream`
-
-Note that only `multipart/*` media types with named parts can be described as shown here. Note also that while `multipart/form-data` originally defined a per-part `Content-Transfer-Encoding` header that could indicate base64 encoding (`format: byte`), it has been deprecated for use with HTTP as of [RFC7578](https://www.rfc-editor.org/rfc/rfc7578#section-4.7).
-
-Examples:
-
-```yaml
-requestBody:
- content:
- multipart/form-data:
- schema:
- type: object
- properties:
- id:
- type: string
- format: uuid
- address:
- # default Content-Type for objects is `application/json`
- type: object
- properties: {}
- profileImage:
- # default Content-Type for string/binary is `application/octet-stream`
- type: string
- format: binary
- children:
- # default Content-Type for arrays is based on the `inner` type (text/plain here)
- type: array
- items:
- type: string
- addresses:
- # default Content-Type for arrays is based on the `inner` type (object shown, so `application/json` in this example)
- type: array
- items:
- $ref: '#/components/schemas/Address'
-```
-
-An `encoding` attribute is introduced to give you control over the serialization of parts of `multipart` request bodies. This attribute is _only_ applicable to request bodies, and _only_ for `multipart` and `application/x-www-form-urlencoded` media types.
+See [Encoding `multipart` Media Types](#encoding-multipart-media-types) for further guidance and examples, both with and without the `encoding` attribute.
#### Encoding Object
@@ -1702,6 +1596,8 @@ In both cases, their order is implementation-defined.
See [Appendix E](#percentEncodingAndFormMediaTypes) for a detailed examination of percent-encoding concerns for form media types.
+##### Fixed Fields
+
###### Common Fixed Fields
These fields MAY be used either with or without the RFC6570-style serialization fields defined in the next section below.
@@ -1727,7 +1623,7 @@ Determining how to handle `null` values if `nullable: true` is present depends o
If `null` values are entirely omitted, then the `contentType` is irrelevant.
See [Appendix B](#dataTypeConversion) for a discussion of data type conversion options.
-##### Fixed Fields for RFC6570-style Serialization
+###### Fixed Fields for RFC6570-style Serialization
Field Name | Type | Description
---|:---:|---
@@ -1750,7 +1646,96 @@ However, if all three of `style`, `explode`, and `allowReserved` fields are abse
This makes the presence of at least one of `style`, `explode`, or `allowReserved` with an explicit value equivalent to using `schema` with `in: query` Parameter Objects, and their absence the equivalent of using `content`, but with the media type specified in `contentType` rather than through a Media Type Object.
-###### Encoding `multipart` Media Types
+##### 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](#mediaTypeObject) under the [Request Body Object](#requestBodyObject).
+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 [Appendix E](#percentEncodingAndFormMediaTypes) for a detailed examination of percent-encoding concerns for form media types.
+
+###### Example: URL Encoded Form with JSON Values
+
+When there is no [`encoding` field](#mediaTypeEncoding), the serialization strategy is based on the Encoding Object's default values:
+
+```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: {}
+```
+
+With this example, consider an `id` of `f81d4fae-7dec-11d0-a765-00a0c91e6bf6` and a US-style address (with ZIP+4) as follows:
+
+```json
+{
+ "streetAddress": "123 Example Dr.",
+ "city": "Somewhere",
+ "state": "CA",
+ "zip": "99999+1234"
+}
+```
+
+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:
+
+```urlencoded
+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
+```
+
+Note that the `id` keyword is treated as `text/plain` per the [Encoding Object](#encodingObject)'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`.
+
+Here is the `id` parameter (without `address`) serialized as `application/json` instead of `text/plain`, and then encoded per RFC1866:
+
+```urlencoded
+id=%22f81d4fae-7dec-11d0-a765-00a0c91e6bf6%22
+```
+
+###### 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 "format: byte" is application/octet-stream,
+ # so we need to set image media type(s) in the Encoding Object.
+ type: string
+ format: byte
+ 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:
+
+```urlencoded
+name=example&icon=iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAABGdBTUEAALGPC%2FxhBQAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAAqADAAQAAAABAAAAAgAAAADO0J6QAAAAEElEQVQIHWP8zwACTGCSAQANHQEDqtPptQAAAABJRU5ErkJggg%3D%3D
+```
+
+Note that this base64-encoded value had to be futher percent-encoded, replacing `/` with `%2F` and each of two final `=` padding characters with `%3D`.
+Some base64-decoding implementations may be able to use the string without the padding per [RFC4648 §3.2](https://datatracker.ietf.org/doc/html/rfc4648#section-3.2).
+However, this is not guaranteed and the value would still need to be percent-decoded due to the `%2F`.
+
+##### Encoding `multipart` Media Types
+
+It is common to use `multipart/form-data` as a `Content-Type` when transferring forms as request bodies. In contrast to 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 §4.2](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 §4.3](https://www.rfc-editor.org/rfc/rfc7578.html#section-4.3) for supplying multiple values per form field.
@@ -1765,9 +1750,13 @@ Note also that `Content-Transfer-Encoding` is deprecated for `multipart/form-dat
Using `format: byte` for a multipart field is equivalent to setting `Content-Transfer-Encoding: base64`.
If `format: byte` is used along with setting a different `Content-Transfer-Encoding` value with the `headers` field, the result is undefined.
-##### Encoding Object Example
+Per the JSON Schema specification, `contentMediaType` without `contentEncoding` present is treated as if `contentEncoding: identity` were present. While useful for embedding text documents such as `text/html` into JSON strings, it is not useful for a `multipart/form-data` part, as it just causes the document to be treated as `text/plain` instead of its actual media type. Use the Encoding Object without `contentMediaType` if no `contentEncoding` is required.
+
+See [Appendix E](#percentEncodingAndFormMediaTypes) for a detailed examination of percent-encoding concerns for form media types.
+
+###### Example: Basic Multipart Form
-`multipart/form-data` allows for binary parts:
+When the `encoding` attribute is _not_ used, the encoding is determined by the Encoding Object's defaults:
```yaml
requestBody:
@@ -1777,28 +1766,58 @@ requestBody:
type: object
properties:
id:
- # default is text/plain
+ # default for primitives without a special format is text/plain
type: string
format: uuid
- address:
- # default is application/json
- type: object
- properties: {}
- historyMetadata:
- # need to declare XML format!
- description: metadata in XML format
- type: object
- properties: {}
profileImage:
- # default is application/octet-stream, need to declare an image type only!
+ # 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:
- historyMetadata:
+ 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/jpeg
+ # only accept png or jpeg
contentType: image/png, image/jpeg
headers:
X-Rate-Limit-Limit:
@@ -1807,24 +1826,23 @@ requestBody:
type: integer
```
-`application/x-www-form-urlencoded` is a text format, which requires base64-encoding any binary data:
+###### Example: Multipart Form with Multiple Files
-```YAML
+In accordance with [RFC7578 §4.3](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:
- application/x-www-form-urlencoded:
+ multipart/form-data:
schema:
- type: object
properties:
- name:
- type: string
- icon:
- # default is text/plain, need to declare an image type only!
- type: string
- format: byte
- encoding:
- icon:
- contentType: image/png, image/jpeg
+ # The property name 'file' will be used for all files.
+ file:
+ type: array
+ items:
+ type: string
+ format: binary
+
```
#### Responses Object
@@ -2483,7 +2501,9 @@ The Header Object follows the structure of the [Parameter Object](#parameterObje
1. `in` MUST NOT be specified, it is implicitly in `header`.
1. All traits that are affected by the location MUST be applicable to a location of `header` (for example, [`style`](#parameterStyle)). This means that `allowEmptyValue` and `allowReserved` MUST NOT be used, and `style`, if used, MUST be limited to `simple`.
-##### Common Fixed Fields
+##### Fixed Fields
+
+###### Common Fixed Fields
These fields MAY be used with either `content` or `schema`.
@@ -2495,7 +2515,7 @@ Field Name | Type | Description
This object MAY be extended with [Specification Extensions](#specificationExtensions).
-##### Fixed Fields for use with `schema`
+###### Fixed Fields for use with `schema`
For simpler scenarios, a [`schema`](#headerSchema) and [`style`](#headerStyle) can describe the structure and syntax of the header.
When `example` or `examples` are provided in conjunction with the `schema` object, the example MUST follow the prescribed serialization strategy for the header.
@@ -2515,7 +2535,7 @@ Field Name | Type | Description
See also [Appendix C: Using RFC6570 Implementations](#usingRFC6570Implementations) for additional guidance.
-##### Fixed Fields for use with `content`
+###### Fixed Fields for use with `content`
For more complex scenarios, the [`content`](#headerContent) property can define the media type and schema of the header, as well as give examples of its use.
Using `content` with a `text/plain` media type is RECOMMENDED for headers where the `schema` strategy is not appropriate.