From 83ef7a06c8dd6ceab512a07bc4b52792d463a848 Mon Sep 17 00:00:00 2001 From: Karen Etheridge Date: Fri, 31 Oct 2025 14:02:15 -0700 Subject: [PATCH 01/10] remove unneeded span markup this was added in commit 9739dfe5afa8, but now that the leading "?" has been removed, this is no longer needed --- src/oas.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/oas.md b/src/oas.md index 86aebf95c4..fd10413804 100644 --- a/src/oas.md +++ b/src/oas.md @@ -923,15 +923,15 @@ The following table shows serialized examples, as would be shown with the `seria | label | true | _empty_ | .blue | .blue.black.brown | .R=100.G=200.B=150 | | simple | false | _empty_ | blue | blue,black,brown | R,100,G,200,B,150 | | simple | true | _empty_ | blue | blue,black,brown | R=100,G=200,B=150 | -| form | false | color= | color=blue | color=blue,black,brown | color=R,100,G,200,B,150 | -| form | true | color= | color=blue | color=blue&color=black&color=brown | R=100&G=200&B=150 | -| spaceDelimited | false | _n/a_ | _n/a_ | color=blue%20black%20brown | color=R%20100%20G%20200%20B%20150 | +| form | false | color= | color=blue | color=blue,black,brown | color=R,100,G,200,B,150 | +| form | true | color= | color=blue | color=blue&color=black&color=brown | R=100&G=200&B=150 | +| spaceDelimited | false | _n/a_ | _n/a_ | color=blue%20black%20brown | color=R%20100%20G%20200%20B%20150 | | spaceDelimited | true | _n/a_ | _n/a_ | _n/a_ | _n/a_ | -| pipeDelimited | false | _n/a_ | _n/a_ | color=blue%7Cblack%7Cbrown | color=R%7C100%7CG%7C200%7CB%7C150 | +| pipeDelimited | false | _n/a_ | _n/a_ | color=blue%7Cblack%7Cbrown | color=R%7C100%7CG%7C200%7CB%7C150 | | pipeDelimited | true | _n/a_ | _n/a_ | _n/a_ | _n/a_ | -| deepObject | _n/a_ | _n/a_ | _n/a_ | _n/a_ | color%5BR%5D=100&color%5BG%5D=200&color%5BB%5D=150 | -| cookie | false | color= | color=blue | color=blue,black,brown | color=R,100,G,200,B,150 | -| cookie | true | color= | color=blue | color=blue; color=black; color=brown | R=100; G=200; B=150 | +| deepObject | _n/a_ | _n/a_ | _n/a_ | _n/a_ | color%5BR%5D=100&color%5BG%5D=200&color%5BB%5D=150 | +| cookie | false | color= | color=blue | color=blue,black,brown | color=R,100,G,200,B,150 | +| cookie | true | color= | color=blue | color=blue; color=black; color=brown | R=100; G=200; B=150 | #### Extending Support for Querystring Formats From 37b058d62d9270e0c84dfab0bb43b650daf6f816 Mon Sep 17 00:00:00 2001 From: Karen Etheridge Date: Sat, 15 Nov 2025 14:24:44 -0800 Subject: [PATCH 02/10] "undefined" in URI Templates is not just null, but can be other things ..such as an empty array or object --- src/oas.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oas.md b/src/oas.md index fd10413804..f0eb36af5c 100644 --- a/src/oas.md +++ b/src/oas.md @@ -4908,7 +4908,7 @@ parameters: type: string ``` -This example is equivalent to RFC6570's `{?foo*,bar}`, and **NOT** `{?foo*}{&bar}`. The latter is problematic because if `foo` is not defined, the result will be an invalid URI. +This example is equivalent to RFC6570's `{?foo*,bar}`, and **NOT** `{?foo*}{&bar}`. The latter is problematic because if `foo` is not defined (see [RFC6570 ยง3.2](https://www.rfc-editor.org/rfc/rfc6570#section-3.2) ) for details on what is considered undefined), the result will be an invalid URI. The `&` prefix operator has no equivalent in the Parameter Object. Note that RFC6570 does not specify behavior for compound values beyond the single level addressed by `explode`. The result of using objects or arrays where no behavior is clearly specified for them is implementation-defined. From b55b1411e2376cd54b60af062c552eacc81aa945 Mon Sep 17 00:00:00 2001 From: Karen Etheridge Date: Sat, 15 Nov 2025 14:31:14 -0800 Subject: [PATCH 03/10] the schema isn't just for specifying the expected type --- src/oas.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oas.md b/src/oas.md index f0eb36af5c..79daced31e 100644 --- a/src/oas.md +++ b/src/oas.md @@ -820,7 +820,7 @@ In these cases, implementations MUST pass values through unchanged rather than a | style | `string` | Describes how the parameter value will be serialized depending on the type of the parameter value. Default values (based on value of `in`): for `"query"` - `"form"`; for `"path"` - `"simple"`; for `"header"` - `"simple"`; for `"cookie"` - `"form"` (for compatibility reasons; note that `style: "cookie"` SHOULD be used with `in: "cookie"`; see [Appendix D](#appendix-d-serializing-headers-and-cookies) for details). | | explode | `boolean` | When this is true, parameter values of type `array` or `object` generate separate parameters for each value of the array or key-value pair of the map. For other types of parameters, or when [`style`](#parameter-style) is `"deepObject"`, this field has no effect. When `style` is `"form"` or `"cookie"`, the default value is `true`. For all other styles, the default value is `false`. | | allowReserved | `boolean` | When this is true, parameter values are serialized using reserved expansion, as defined by [RFC6570](https://datatracker.ietf.org/doc/html/rfc6570#section-3.2.3), which allows [RFC3986's reserved character set](https://datatracker.ietf.org/doc/html/rfc3986#section-2.2), as well as percent-encoded triples, to pass through unchanged, while still percent-encoding all other disallowed characters (including `%` outside of percent-encoded triples). Applications are still responsible for percent-encoding reserved characters that are not allowed by the rules of the `in` destination or media type, or are [not allowed in the path by this specification](#path-templating); see [URL Percent-Encoding](#url-percent-encoding) for details. The default value is `false`. This field only applies to `in` and `style` values that automatically percent-encode. | -| schema | [Schema Object](#schema-object) | The schema defining the type used for the parameter. | +| schema | [Schema Object](#schema-object) | The schema defining the type and other constraints used for the parameter. | See also [Appendix C: Using RFC6570-Based Serialization](#appendix-c-using-rfc6570-based-serialization) for additional guidance. From bcdfd400ec9193ca4d794155a4a7545224b63a1f Mon Sep 17 00:00:00 2001 From: Karen Etheridge Date: Sat, 15 Nov 2025 14:34:08 -0800 Subject: [PATCH 04/10] as per section 4.8.2, path parameter names cannot contain braces --- src/schemas/validation/schema.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/schemas/validation/schema.yaml b/src/schemas/validation/schema.yaml index bdc429c078..3f8976bb1f 100644 --- a/src/schemas/validation/schema.yaml +++ b/src/schemas/validation/schema.yaml @@ -439,6 +439,8 @@ $defs: const: path then: properties: + name: + pattern: '^[^{}]+$' style: default: simple enum: From 38ad36459490385e5cc5301499b946a198358980 Mon Sep 17 00:00:00 2001 From: Karen Etheridge Date: Sun, 23 Nov 2025 13:08:42 -0800 Subject: [PATCH 05/10] allowReserved only permitted where percent-encoding is done namely: in=path, in=query, in=cookie+style=form, but not in=header, in=querystring or in=cookie+style=cookie and not in encoding objects where contentType is used (none of style, explode, allowReserved are present) this brings in some work that didn't get merged in #4904 ..and also fixes a bad $ref URI --- src/oas.md | 2 +- src/schemas/validation/schema.yaml | 31 ++++++++++++------- .../fail/header-object-allowReserved.yaml | 12 +++++++ ...parameter-object-cookie-allowReserved.yaml | 12 +++++++ ...parameter-object-header-allowReserved.yaml | 11 +++++++ tests/schema/pass/header-object-examples.yaml | 3 +- ...eter-object-cookie-form-allowReserved.yaml | 18 +++++++++++ .../parameter-object-path-allowReserved.yaml | 12 +++++++ .../parameter-object-query-allowReserved.yaml | 11 +++++++ 9 files changed, 97 insertions(+), 15 deletions(-) create mode 100644 tests/schema/fail/header-object-allowReserved.yaml create mode 100644 tests/schema/fail/parameter-object-cookie-allowReserved.yaml create mode 100644 tests/schema/fail/parameter-object-header-allowReserved.yaml create mode 100644 tests/schema/pass/parameter-object-cookie-form-allowReserved.yaml create mode 100644 tests/schema/pass/parameter-object-path-allowReserved.yaml create mode 100644 tests/schema/pass/parameter-object-query-allowReserved.yaml diff --git a/src/oas.md b/src/oas.md index 79daced31e..213316c261 100644 --- a/src/oas.md +++ b/src/oas.md @@ -819,7 +819,7 @@ In these cases, implementations MUST pass values through unchanged rather than a | ---- | :----: | ---- | | style | `string` | Describes how the parameter value will be serialized depending on the type of the parameter value. Default values (based on value of `in`): for `"query"` - `"form"`; for `"path"` - `"simple"`; for `"header"` - `"simple"`; for `"cookie"` - `"form"` (for compatibility reasons; note that `style: "cookie"` SHOULD be used with `in: "cookie"`; see [Appendix D](#appendix-d-serializing-headers-and-cookies) for details). | | explode | `boolean` | When this is true, parameter values of type `array` or `object` generate separate parameters for each value of the array or key-value pair of the map. For other types of parameters, or when [`style`](#parameter-style) is `"deepObject"`, this field has no effect. When `style` is `"form"` or `"cookie"`, the default value is `true`. For all other styles, the default value is `false`. | -| allowReserved | `boolean` | When this is true, parameter values are serialized using reserved expansion, as defined by [RFC6570](https://datatracker.ietf.org/doc/html/rfc6570#section-3.2.3), which allows [RFC3986's reserved character set](https://datatracker.ietf.org/doc/html/rfc3986#section-2.2), as well as percent-encoded triples, to pass through unchanged, while still percent-encoding all other disallowed characters (including `%` outside of percent-encoded triples). Applications are still responsible for percent-encoding reserved characters that are not allowed by the rules of the `in` destination or media type, or are [not allowed in the path by this specification](#path-templating); see [URL Percent-Encoding](#url-percent-encoding) for details. The default value is `false`. This field only applies to `in` and `style` values that automatically percent-encode. | +| allowReserved | `boolean` | When this is true, parameter values are serialized using reserved expansion, as defined by [RFC6570](https://datatracker.ietf.org/doc/html/rfc6570#section-3.2.3), which allows [RFC3986's reserved character set](https://datatracker.ietf.org/doc/html/rfc3986#section-2.2), as well as percent-encoded triples, to pass through unchanged, while still percent-encoding all other disallowed characters (including `%` outside of percent-encoded triples). Applications are still responsible for percent-encoding reserved characters that are not allowed by the rules of the `in` destination or media type, or are [not allowed in the path by this specification](#path-templating); see [URL Percent-Encoding](#url-percent-encoding) for details. The default value is `false`. This field only applies to `in` and `style` values that automatically percent-encode (that is: `in: path`, `in: query`, and `in: cookie` with `style: form`). | | schema | [Schema Object](#schema-object) | The schema defining the type and other constraints used for the parameter. | See also [Appendix C: Using RFC6570-Based Serialization](#appendix-c-using-rfc6570-based-serialization) for additional guidance. diff --git a/src/schemas/validation/schema.yaml b/src/schemas/validation/schema.yaml index 3f8976bb1f..078af4708c 100644 --- a/src/schemas/validation/schema.yaml +++ b/src/schemas/validation/schema.yaml @@ -421,9 +421,6 @@ $defs: type: string explode: type: boolean - allowReserved: - default: false - type: boolean allOf: - $ref: '#/$defs/parameter/dependentSchemas/schema/$defs/styles-for-path' - $ref: '#/$defs/parameter/dependentSchemas/schema/$defs/styles-for-header' @@ -449,6 +446,9 @@ $defs: - simple required: const: true + allowReserved: + type: boolean + default: false required: - required @@ -477,6 +477,9 @@ $defs: - spaceDelimited - pipeDelimited - deepObject + allowReserved: + type: boolean + default: false styles-for-cookie: if: @@ -490,6 +493,15 @@ $defs: enum: - form - cookie + if: + properties: + style: + const: form + then: + properties: + allowReserved: + type: boolean + default: false unevaluatedProperties: false @@ -598,6 +610,7 @@ $defs: type: boolean allowReserved: type: boolean + default: false encoding: type: object additionalProperties: @@ -614,9 +627,7 @@ $defs: prefixEncoding: false itemEncoding: false style: - properties: - allowReserved: - default: false + $ref: '#/$defs/styles-for-form' explode: properties: style: @@ -627,9 +638,8 @@ $defs: properties: style: default: form - allOf: - - $ref: '#/$defs/specification-extensions' - - $ref: '#/$defs/styles-for-form' + $ref: '#/$defs/styles-for-form' + $ref: '#/$defs/specification-extensions' unevaluatedProperties: false responses: @@ -810,9 +820,6 @@ $defs: explode: default: false type: boolean - allowReserved: - default: false - type: boolean allOf: - $ref: '#/$defs/examples' - $ref: '#/$defs/specification-extensions' diff --git a/tests/schema/fail/header-object-allowReserved.yaml b/tests/schema/fail/header-object-allowReserved.yaml new file mode 100644 index 0000000000..8ee2ff7850 --- /dev/null +++ b/tests/schema/fail/header-object-allowReserved.yaml @@ -0,0 +1,12 @@ +openapi: 3.3.0 +info: + title: allowReserved only permitted with in and style values that percent-encode + version: 1.0.0 +components: + headers: + Style: + schema: + type: array + style: simple + explode: true + allowReserved: true diff --git a/tests/schema/fail/parameter-object-cookie-allowReserved.yaml b/tests/schema/fail/parameter-object-cookie-allowReserved.yaml new file mode 100644 index 0000000000..b724613a1c --- /dev/null +++ b/tests/schema/fail/parameter-object-cookie-allowReserved.yaml @@ -0,0 +1,12 @@ +openapi: 3.3.0 +info: + title: allowReserved only permitted with in and style values that percent-encode + version: 1.0.0 +components: + parameters: + my_cookie: + name: my_cookie + in: cookie + style: cookie + allowReserved: true + schema: {} diff --git a/tests/schema/fail/parameter-object-header-allowReserved.yaml b/tests/schema/fail/parameter-object-header-allowReserved.yaml new file mode 100644 index 0000000000..d9c7d292d7 --- /dev/null +++ b/tests/schema/fail/parameter-object-header-allowReserved.yaml @@ -0,0 +1,11 @@ +openapi: 3.3.0 +info: + title: allowReserved only permitted with in and style values that percent-encode + version: 1.0.0 +components: + parameters: + header: + name: my-header + in: header + allowReserved: false + schema: {} diff --git a/tests/schema/pass/header-object-examples.yaml b/tests/schema/pass/header-object-examples.yaml index 22c3941d9a..7c86d16789 100644 --- a/tests/schema/pass/header-object-examples.yaml +++ b/tests/schema/pass/header-object-examples.yaml @@ -17,10 +17,9 @@ components: type: string pattern: ^" Reference: - $ref: '#/components/schemas/ETag' + $ref: '#/components/headers/ETag' Style: schema: type: array style: simple explode: true - allowReserved: true \ No newline at end of file diff --git a/tests/schema/pass/parameter-object-cookie-form-allowReserved.yaml b/tests/schema/pass/parameter-object-cookie-form-allowReserved.yaml new file mode 100644 index 0000000000..887de70a32 --- /dev/null +++ b/tests/schema/pass/parameter-object-cookie-form-allowReserved.yaml @@ -0,0 +1,18 @@ +openapi: 3.3.0 +info: + title: allowReserved only permitted with in and style values that percent-encode + version: 1.0.0 +components: + parameters: + style_form: + name: my_form_cookie + in: cookie + # default style is form, therefore allowReserved is allowed + allowReserved: true + schema: {} + style_cookie: + name: my_cookie_cookie + in: cookie + style: cookie + # no percent decoding for style=cookie, therefore allowReserved is not allowed + schema: {} diff --git a/tests/schema/pass/parameter-object-path-allowReserved.yaml b/tests/schema/pass/parameter-object-path-allowReserved.yaml new file mode 100644 index 0000000000..8c45ca2d0a --- /dev/null +++ b/tests/schema/pass/parameter-object-path-allowReserved.yaml @@ -0,0 +1,12 @@ +openapi: 3.3.0 +info: + title: api + version: 1.0.0 +components: + parameters: + path: + name: my-path + in: path + required: true + allowReserved: false + schema: {} diff --git a/tests/schema/pass/parameter-object-query-allowReserved.yaml b/tests/schema/pass/parameter-object-query-allowReserved.yaml new file mode 100644 index 0000000000..e6c471357e --- /dev/null +++ b/tests/schema/pass/parameter-object-query-allowReserved.yaml @@ -0,0 +1,11 @@ +openapi: 3.3.0 +info: + title: allowReserved only permitted with in and style values that percent-encode + version: 1.0.0 +components: + parameters: + my_query: + name: my_query + in: query + allowReserved: true + schema: {} From e24e5bb8754328b37f288e757ae9ffb17e680134 Mon Sep 17 00:00:00 2001 From: Karen Etheridge Date: Sun, 23 Nov 2025 13:46:24 -0800 Subject: [PATCH 06/10] fix style, explode, allowReserved defaults for parameter and encoding objects - explode defaults were wrong for in: cookie, style: cookie, and for encoding object - allowReserved defaults were wrong for encoding object in parameter objects: - explode: always false for "in: path", "in: header" - explode: always true for "in: cookie" (both "style: form" and "style: cookie" default to "explode: true") - explode: only true for "in: query" when "style: form" (the default style for this location) in encoding objects: - style: default is "form", but only when "explode" or "allowReserved" are present - explode: default is true when "style: form" (the default style) and otherwise false, and not included at all unless "style" or "allowReserved" are present - allowReserved: default is false, but only when "style" or "explode" are present that is: when none of style, explode or allowReserved are present, "contentType" is used (or a default is calculated), so none of style, explode or allowReserved shall have default values --- src/schemas/validation/schema.yaml | 22 +++++++++++++------ .../pass/parameter-object-examples.yaml | 4 ++++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/schemas/validation/schema.yaml b/src/schemas/validation/schema.yaml index 078af4708c..d26e25f5ec 100644 --- a/src/schemas/validation/schema.yaml +++ b/src/schemas/validation/schema.yaml @@ -426,7 +426,6 @@ $defs: - $ref: '#/$defs/parameter/dependentSchemas/schema/$defs/styles-for-header' - $ref: '#/$defs/parameter/dependentSchemas/schema/$defs/styles-for-query' - $ref: '#/$defs/parameter/dependentSchemas/schema/$defs/styles-for-cookie' - - $ref: '#/$defs/styles-for-form' $defs: styles-for-path: @@ -446,6 +445,8 @@ $defs: - simple required: const: true + explode: + default: false allowReserved: type: boolean default: false @@ -462,6 +463,8 @@ $defs: style: default: simple const: simple + explode: + default: false styles-for-query: if: @@ -480,6 +483,7 @@ $defs: allowReserved: type: boolean default: false + $ref: '#/$defs/explode-for-form' styles-for-cookie: if: @@ -493,6 +497,8 @@ $defs: enum: - form - cookie + explode: + default: true if: properties: style: @@ -502,6 +508,7 @@ $defs: allowReserved: type: boolean default: false + $ref: '#/$defs/explode-for-form' unevaluatedProperties: false @@ -610,7 +617,6 @@ $defs: type: boolean allowReserved: type: boolean - default: false encoding: type: object additionalProperties: @@ -627,7 +633,10 @@ $defs: prefixEncoding: false itemEncoding: false style: - $ref: '#/$defs/styles-for-form' + properties: + allowReserved: + default: false + $ref: '#/$defs/explode-for-form' explode: properties: style: @@ -638,7 +647,7 @@ $defs: properties: style: default: form - $ref: '#/$defs/styles-for-form' + $ref: '#/$defs/explode-for-form' $ref: '#/$defs/specification-extensions' unevaluatedProperties: false @@ -1127,13 +1136,12 @@ $defs: additionalProperties: type: string - styles-for-form: + explode-for-form: + $comment: for encoding objects, and query and cookie parameters, style=form is the default if: properties: style: const: form - required: - - style then: properties: explode: diff --git a/tests/schema/pass/parameter-object-examples.yaml b/tests/schema/pass/parameter-object-examples.yaml index feaf6d449f..051d91865c 100644 --- a/tests/schema/pass/parameter-object-examples.yaml +++ b/tests/schema/pass/parameter-object-examples.yaml @@ -9,6 +9,7 @@ paths: in: header description: token to be passed as a header required: true + explode: false schema: type: array items: @@ -19,6 +20,7 @@ paths: in: path description: username to fetch required: true + explode: false schema: type: string - name: id @@ -55,10 +57,12 @@ paths: - in: cookie name: my_cookie1 style: form + explode: true schema: {} - in: cookie name: my_cookie2 style: cookie + explode: false schema: {} /user: parameters: From c5b0fa52da636578f2547e9e0dd0e79f9433b035 Mon Sep 17 00:00:00 2001 From: Karen Etheridge Date: Tue, 16 Dec 2025 14:59:23 -0800 Subject: [PATCH 07/10] working examples of parameter and encoding object permutations with all defaults omitted tested with: $ openapi-validate --with-defaults tests/schema/pass/style-defaults.yaml { "defaults" : { "/components/mediaTypes/encoding_object_defaults/encoding/allowReserved/explode" : true, "/components/mediaTypes/encoding_object_defaults/encoding/allowReserved/style" : "form", "/components/mediaTypes/encoding_object_defaults/encoding/explode/allowReserved" : false, "/components/mediaTypes/encoding_object_defaults/encoding/explode/style" : "form", "/components/mediaTypes/encoding_object_defaults/encoding/style_form/allowReserved" : false, "/components/mediaTypes/encoding_object_defaults/encoding/style_form/explode" : true, "/components/mediaTypes/encoding_object_defaults/encoding/style_spaceDelimited/allowReserved" : false, "/components/mediaTypes/encoding_object_defaults/encoding/style_spaceDelimited/explode" : false, "/components/parameters/cookie_cookie/deprecated" : false, "/components/parameters/cookie_cookie/explode" : true, "/components/parameters/cookie_cookie/required" : false, "/components/parameters/cookie_form/allowReserved" : false, "/components/parameters/cookie_form/deprecated" : false, "/components/parameters/cookie_form/explode" : true, "/components/parameters/cookie_form/required" : false, "/components/parameters/cookie_form/style" : "form", "/components/parameters/cookie_media_type/deprecated" : false, "/components/parameters/cookie_media_type/required" : false, "/components/parameters/header/allowReserved" : false, "/components/parameters/header/deprecated" : false, "/components/parameters/header/explode" : false, "/components/parameters/header/style" : "simple", "/components/parameters/path_label/allowReserved" : false, "/components/parameters/path_label/deprecated" : false, "/components/parameters/path_label/explode" : false, "/components/parameters/path_matrix/allowReserved" : false, "/components/parameters/path_matrix/deprecated" : false, "/components/parameters/path_matrix/explode" : false, "/components/parameters/path_media_type/deprecated" : false, "/components/parameters/path_simple/allowReserved" : false, "/components/parameters/path_simple/deprecated" : false, "/components/parameters/path_simple/explode" : false, "/components/parameters/path_simple/style" : "simple", "/components/parameters/query_deepObject/allowEmptyValue" : false, "/components/parameters/query_deepObject/allowReserved" : false, "/components/parameters/query_deepObject/deprecated" : false, "/components/parameters/query_deepObject/explode" : false, "/components/parameters/query_deepObject/required" : false, "/components/parameters/query_form/allowEmptyValue" : false, "/components/parameters/query_form/allowReserved" : false, "/components/parameters/query_form/deprecated" : false, "/components/parameters/query_form/explode" : true, "/components/parameters/query_form/required" : false, "/components/parameters/query_form/style" : "form", "/components/parameters/query_media_type/allowEmptyValue" : false, "/components/parameters/query_media_type/deprecated" : false, "/components/parameters/query_media_type/required" : false, "/components/parameters/query_pipeDelimited/allowEmptyValue" : false, "/components/parameters/query_pipeDelimited/allowReserved" : false, "/components/parameters/query_pipeDelimited/deprecated" : false, "/components/parameters/query_pipeDelimited/explode" : false, "/components/parameters/query_pipeDelimited/required" : false, "/components/parameters/query_spaceDelimited/allowEmptyValue" : false, "/components/parameters/query_spaceDelimited/allowReserved" : false, "/components/parameters/query_spaceDelimited/deprecated" : false, "/components/parameters/query_spaceDelimited/explode" : false, "/components/parameters/query_spaceDelimited/required" : false, "/jsonSchemaDialect" : "https://spec.openapis.org/oas/3.2/dialect/WORK-IN-PROGRESS", "/servers" : [ { "url" : "/" } ] }, "valid" : true } (executable is part of https://github.com/karenetheridge/OpenAPI-Modern) --- src/schemas/validation/schema.yaml | 1 - tests/schema/pass/style-defaults.yaml | 105 ++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 tests/schema/pass/style-defaults.yaml diff --git a/src/schemas/validation/schema.yaml b/src/schemas/validation/schema.yaml index d26e25f5ec..7d0ed898ff 100644 --- a/src/schemas/validation/schema.yaml +++ b/src/schemas/validation/schema.yaml @@ -508,7 +508,6 @@ $defs: allowReserved: type: boolean default: false - $ref: '#/$defs/explode-for-form' unevaluatedProperties: false diff --git a/tests/schema/pass/style-defaults.yaml b/tests/schema/pass/style-defaults.yaml new file mode 100644 index 0000000000..df874bf7b7 --- /dev/null +++ b/tests/schema/pass/style-defaults.yaml @@ -0,0 +1,105 @@ +openapi: 3.3.0 +info: + title: various permutations of parameter objects, with non-required values left to their defaults + version: 1.0.0 +components: + mediaTypes: + encoding_object_defaults: # media type name + encoding: + no_styles: # property name + x-comment: "style, explode and allowReserved are not present, so contentType is used; no defaults expected as default contentType cannot be determined by the schema" + style_form: + x-comment: "expecting defaults: explode=true, allowReserved=false" + style: form + style_spaceDelimited: + x-comment: "expecting defaults: explode=false, allowReserved=false" + style: spaceDelimited + explode: + x-comment: "expecting defaults: style=form, allowReserved=false" + explode: false + allowReserved: + x-comment: "expecting default: style=form, explode=true" + allowReserved: true + parameters: + path_media_type: + x-comment: "expecting defaults: deprecated=false" + name: path_media-type + in: path + required: true + content: + text/*: + schema: {} + path_simple: + x-comment: "expecting defaults: deprecated=false, style=simple, explode=false, allowReserved=false" + name: path_simple + in: path + required: true + schema: {} + path_matrix: + x-comment: "expecting defaults: deprecated=false, explode=false, allowReserved=false" + name: path_matrix + in: path + required: true + style: matrix + schema: {} + path_label: + x-comment: "expecting defaults: deprecated=false, explode=false, allowReserved=false" + name: path_label + in: path + required: true + style: label + schema: {} + query_media_type: + x-comment: "expecting defaults: required=false, deprecated=false, allowEmptyValue=false" + name: query_media_type + in: query + content: + text/*: + schema: {} + query_form: + x-comment: "expecting defaults: required=false, deprecated=false, allowEmptyValue=false, style=form, explode=true, allowReserved=false" + name: query_form + in: query + schema: {} + query_spaceDelimited: + x-comment: "expecting defaults: required=false, deprecated=false, allowEmptyValue=false, explode=false, allowReserved=false" + name: query_spaceDelimited + in: query + style: spaceDelimited + schema: {} + query_pipeDelimited: + x-comment: "expecting defaults: required=false, deprecated=false, allowEmptyValue=false, explode=false, allowReserved=false" + name: query_pipeDelimited + in: query + style: pipeDelimited + schema: {} + query_deepObject: + x-comment: "expecting defaults: required=false, deprecated=false, allowEmptyValue=false, allowReserved=false" + name: query_deepObject + in: query + style: deepObject + schema: {} + header: + x-comment: "expecting defaults: deprecated=false, style=simple, explode=false, allowReserved=false" + name: header + in: path + required: true + schema: {} + cookie_media_type: + x-comment: "expecting defaults: required=false, deprecated=false" + name: cookie_media_type + in: cookie + content: + text/*: + schema: {} + cookie_form: + x-comment: "expecting defaults: required=false, deprecated=false, style=form, explode=true, allowReserved=false" + name: cookie_form + in: cookie + schema: {} + cookie_cookie: + x-comment: "expecting defaults: required=false, deprecated=false, explode=true" + name: cookie_cookie + in: cookie + style: cookie + schema: {} From c564b808302eaef8f57f00a8f267a9aa6faf1475 Mon Sep 17 00:00:00 2001 From: Karen Etheridge Date: Sat, 24 Jan 2026 11:48:43 -0800 Subject: [PATCH 08/10] fix broken examples --- src/oas.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/oas.md b/src/oas.md index 213316c261..677676b8e0 100644 --- a/src/oas.md +++ b/src/oas.md @@ -1091,15 +1091,17 @@ content: long: type: number examples: - dataValue: - lat: 10 - long: 60 - serializedValue: '{"lat":10,"long":60}' + 'New York': + dataValue: + lat: 40.6 + long: -73.9 + serializedValue: '{"lat":40.6,"long":-73.9}' examples: - dataValue: - lat: 10 - long: 60 - serializedValue: coordinates=%7B%22lat%22%3A10%2C%22long%22%3A60%7D + 'New York': + dataValue: + lat: 40.6 + long: -73.9 + serializedValue: coordinates=%7B%22lat%22%3A40.6%2C%22long%22%3A-73.9%7D ``` A querystring parameter using regular form encoding, but managed with a Media Type Object. @@ -1108,6 +1110,7 @@ Examples are shown at both the media type and parameter level to emphasize that, ```yaml in: querystring +name: metadata content: application/x-www-form-urlencoded: schema: From e6cc2e08448a91c0c5b26837699c46b9a878e81a Mon Sep 17 00:00:00 2001 From: Karen Etheridge Date: Sat, 15 Nov 2025 14:31:04 -0800 Subject: [PATCH 09/10] mention deserialization too --- src/oas.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oas.md b/src/oas.md index 677676b8e0..1756a94a35 100644 --- a/src/oas.md +++ b/src/oas.md @@ -776,7 +776,7 @@ There are five possible parameter locations specified by the `in` field: #### Fixed Fields -The rules for serialization of the parameter are specified in one of two ways. +The rules for serialization and deserialization of the parameter are specified in one of two ways. Parameter Objects MUST include either a `content` field or a `schema` field, but not both. See [Appendix B](#appendix-b-data-type-conversion) for a discussion of converting values of various types to string representations. From 6603f7032a46c42a6044494b0c9401a22444b40a Mon Sep 17 00:00:00 2001 From: Karen Etheridge Date: Sat, 15 Nov 2025 14:31:04 -0800 Subject: [PATCH 10/10] specify how query parameters are added to the URL ..and remove example that is specific to a particular style, explode and schema type configuration --- src/oas.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oas.md b/src/oas.md index 1756a94a35..77d951cf4c 100644 --- a/src/oas.md +++ b/src/oas.md @@ -769,7 +769,7 @@ See [Appendix E](#appendix-e-percent-encoding-and-form-media-types) for a detail There are five possible parameter locations specified by the `in` field: * path - Used together with [Path Templating](#path-templating), where the parameter value is actually part of the operation's URL. This does not include the host or base path of the API. For example, in `/items/{itemId}`, the path parameter is `itemId`. -* query - Parameters that are appended to the URL. For example, in `/items?id=###`, the query parameter is `id`; MUST NOT appear in the same operation (or in the operation's path-item) as an `in: "querystring"` parameter. +* query - Parameters that are appended to the URL with the `?` character (or for subsequent query parameters, with the `&` character); MUST NOT appear in the same operation (or in the operation's path-item) as an `in: "querystring"` parameter. * querystring - A parameter that treats the entire URL query string as a value which MUST be specified using the `content` field, most often with media type `application/x-www-form-urlencoded` using [Encoding Objects](#encoding-object) in the same way as with request bodies of that media type; MUST NOT appear more than once, and MUST NOT appear in the same operation (or in the operation's path-item) as any `in: "query"` parameters. * header - Custom headers that are expected as part of the request. Note that [RFC9110](https://www.rfc-editor.org/rfc/rfc9110.html#section-5.1) states header names are case-insensitive. * cookie - Used to pass a specific cookie value to the API.