From aa33fdab2499e7ff43f2d8ca6b6895f4ab93e775 Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Mon, 9 Jun 2025 15:10:44 -0700 Subject: [PATCH 1/3] Support nested Encoding Objects This adds the Media Type Object's encoding field to the Encoding Object to support nested multipart documents. It only requires one level of nesting, but allows implementations to support more. --- src/oas.md | 33 +++++++++++++++++++ src/schemas/validation/schema.yaml | 15 +++++++++ .../fail/encoding-enc-item-exclusion.yaml | 12 +++++++ .../fail/encoding-enc-prefix-exclusion.yaml | 12 +++++++ tests/schema/pass/media-type-examples.yaml | 13 ++++++++ 5 files changed, 85 insertions(+) create mode 100644 tests/schema/fail/encoding-enc-item-exclusion.yaml create mode 100644 tests/schema/fail/encoding-enc-prefix-exclusion.yaml diff --git a/src/oas.md b/src/oas.md index e91c9cb08a..0f0eb10fd9 100644 --- a/src/oas.md +++ b/src/oas.md @@ -1641,6 +1641,9 @@ These fields MAY be used either with or without the RFC6570-style serialization | ---- | :----: | ---- | | contentType | `string` | The `Content-Type` for encoding a specific property. The value is a comma-separated list, each element of which is either a specific media type (e.g. `image/png`) or a wildcard media type (e.g. `image/*`). Default value depends on the property type as shown in the table below. | | headers | Map[`string`, [Header Object](#header-object) \| [Reference Object](#reference-object)] | A map allowing additional information to be provided as headers. `Content-Type` is described separately and SHALL be ignored in this section. This field SHALL be ignored if the media type is not a `multipart`. | +| encoding | Map[`string`, [Encoding Object](#encoding-object)] | Applies nested Encoding Objects in the same manner as the [Media Type Object](#media-type-object)'s `encoding` field. | +| prefixEncoding | [[Encoding Object](#encoding-object)] | Applies nested Encoding Objects in the same manner as the [Media Type Object](#media-type-object)'s `prefixEncoding` field. | +| itemEncoding | [Encoding Object](#encoding-object) | Applies nested Encoding Objects in the same manner as the [Media Type Object](#media-type-object)'s `itemEncoding` field. | This object MAY be extended with [Specification Extensions](#specification-extensions). @@ -1674,6 +1677,12 @@ 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. +##### Nested Encoding + +Nested formats requiring encoding, most notably nested `multipart/mixed`, can be supported with this Object's `encoding`, `prefixEncoding`, and / or `itemEncoding` fields. +Implementations MUST support one level of nesting, and MAY support additional levels. +If supporting additional levels, any limits on nesting levels MUST be documented. + ##### Encoding the `x-www-form-urlencoded` Media Type To work with 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). @@ -1869,6 +1878,30 @@ requestBody: 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`. +###### Example: Nested `multipart/mixed` + +This defines a two-part `multipart/mixed` where the first part is JSON and the second part is a nested `multipart/mixed` document. +The nested parts are JSON, plain text, and a PNG image. + +```yaml +multipart/mixed: + schema: + type: array + prefixItems: + - type: array + - prefixItems: + - type: object + - type: string + - {} + prefixEncoding: + - {} # Accept the default application/json + - contentType: multipart/mixed + prefixEncoding: + - contentType: application/xml + - {} # Accept the default text/plain + - contentType: image/png +``` + #### Responses Object A container for the expected responses of an operation. diff --git a/src/schemas/validation/schema.yaml b/src/schemas/validation/schema.yaml index 9990fefb67..d79902c765 100644 --- a/src/schemas/validation/schema.yaml +++ b/src/schemas/validation/schema.yaml @@ -561,9 +561,24 @@ $defs: allowReserved: default: false type: boolean + encoding: + type: object + additionalProperties: + $ref: '#/$defs/encoding' + prefixEncoding: + type: array + items: + $ref: '#/$defs/encoding' + itemEncoding: + $ref: '#/$defs/encoding' allOf: - $ref: '#/$defs/specification-extensions' - $ref: '#/$defs/styles-for-form' + - dependentSchemas: + encoding: + properties: + prefixEncoding: false + itemEncoding: false unevaluatedProperties: false responses: diff --git a/tests/schema/fail/encoding-enc-item-exclusion.yaml b/tests/schema/fail/encoding-enc-item-exclusion.yaml new file mode 100644 index 0000000000..658f848be9 --- /dev/null +++ b/tests/schema/fail/encoding-enc-item-exclusion.yaml @@ -0,0 +1,12 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +components: + requestBodies: + content: + multipart/mixed: + prefixEncoding: + - contentType: multipart/mixed + encoding: {} + prefixEncoding: [] diff --git a/tests/schema/fail/encoding-enc-prefix-exclusion.yaml b/tests/schema/fail/encoding-enc-prefix-exclusion.yaml new file mode 100644 index 0000000000..8f62070d3b --- /dev/null +++ b/tests/schema/fail/encoding-enc-prefix-exclusion.yaml @@ -0,0 +1,12 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +components: + requestBodies: + content: + multipart/mixed: + prefixEncoding: + - contentType: multipart/mixed + encoding: {} + itemEncoding: [] diff --git a/tests/schema/pass/media-type-examples.yaml b/tests/schema/pass/media-type-examples.yaml index 2ab4e68076..72470f82e0 100644 --- a/tests/schema/pass/media-type-examples.yaml +++ b/tests/schema/pass/media-type-examples.yaml @@ -117,6 +117,10 @@ paths: type: string forCoverage2: type: string + nested1: + type: object + nested2: + type: array encoding: addresses: # require XML Content-Type in utf-8 encoding @@ -138,3 +142,12 @@ paths: forCoverage2: style: spaceDelimited explode: true + nested1: + contentType: multipart/form-data + encoding: + inner: {} + nested2: + contentType: multipart/mixed + prefixEncoding: + - {} + itemEncoding: {} From 5f9ce8e12b666b65df826c0e03b638ed1ac25c96 Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Fri, 18 Jul 2025 12:32:50 -0700 Subject: [PATCH 2/3] Fix example thanks to review feedback --- src/oas.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/oas.md b/src/oas.md index 0f0eb10fd9..9ebd1d5277 100644 --- a/src/oas.md +++ b/src/oas.md @@ -1880,8 +1880,8 @@ As seen in the [Encoding Object's `contentType` field documentation](#encoding-c ###### Example: Nested `multipart/mixed` -This defines a two-part `multipart/mixed` where the first part is JSON and the second part is a nested `multipart/mixed` document. -The nested parts are JSON, plain text, and a PNG image. +This defines a two-part `multipart/mixed` where the first part is a JSON array and the second part is a nested `multipart/mixed` document. +The nested parts are XML, plain text, and a PNG image. ```yaml multipart/mixed: @@ -1889,7 +1889,8 @@ multipart/mixed: type: array prefixItems: - type: array - - prefixItems: + - type: array + prefixItems: - type: object - type: string - {} From 767bdaf5ab609be93539ff363651e6cac14fc87f Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Sat, 19 Jul 2025 15:20:20 -0700 Subject: [PATCH 3/3] Remove documentation requirement --- src/oas.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/oas.md b/src/oas.md index 9ebd1d5277..ab75857cce 100644 --- a/src/oas.md +++ b/src/oas.md @@ -1681,7 +1681,6 @@ The absence of all three of those fields is the equivalent of using `content`, b Nested formats requiring encoding, most notably nested `multipart/mixed`, can be supported with this Object's `encoding`, `prefixEncoding`, and / or `itemEncoding` fields. Implementations MUST support one level of nesting, and MAY support additional levels. -If supporting additional levels, any limits on nesting levels MUST be documented. ##### Encoding the `x-www-form-urlencoded` Media Type