From 197a309ed744c49a11b1c6e78b81cbf3abfeedff Mon Sep 17 00:00:00 2001 From: Karen Etheridge Date: Fri, 31 Oct 2025 14:02:15 -0700 Subject: [PATCH 01/14] 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 2b839b4554..fd35bb6e4c 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 7226325eaba234fbc456165c255662e62f8cf216 Mon Sep 17 00:00:00 2001 From: Karen Etheridge Date: Sat, 15 Nov 2025 14:24:44 -0800 Subject: [PATCH 02/14] "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 fd35bb6e4c..87de0091cc 100644 --- a/src/oas.md +++ b/src/oas.md @@ -4909,7 +4909,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 §2.3](https://www.rfc-editor.org/rfc/rfc6570#section-2.3) 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 bebbba837a102646b36c337fd78d3b1c46e5c1c6 Mon Sep 17 00:00:00 2001 From: Karen Etheridge Date: Sat, 15 Nov 2025 14:31:14 -0800 Subject: [PATCH 03/14] 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 87de0091cc..fc6a2516eb 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 00e9e33cb3663387f7ec25966c33d5e19f1286da Mon Sep 17 00:00:00 2001 From: Karen Etheridge Date: Sat, 15 Nov 2025 14:34:08 -0800 Subject: [PATCH 04/14] 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 05e5704fe1..b7e7468bbf 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 4097aa7dc21e700b7198ebbab91fb5f00ebd2d83 Mon Sep 17 00:00:00 2001 From: Karen Etheridge Date: Sun, 23 Nov 2025 13:08:42 -0800 Subject: [PATCH 05/14] 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 --- 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 | 1 - ...eter-object-cookie-form-allowReserved.yaml | 18 +++++++++++ .../parameter-object-path-allowReserved.yaml | 12 +++++++ .../parameter-object-query-allowReserved.yaml | 11 +++++++ 9 files changed, 96 insertions(+), 14 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 fc6a2516eb..f43ed08843 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 b7e7468bbf..5dcf44f44e 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..8c448704a2 --- /dev/null +++ b/tests/schema/fail/header-object-allowReserved.yaml @@ -0,0 +1,12 @@ +openapi: 3.2.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..09327beae5 --- /dev/null +++ b/tests/schema/fail/parameter-object-cookie-allowReserved.yaml @@ -0,0 +1,12 @@ +openapi: 3.2.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..6b0a83d016 --- /dev/null +++ b/tests/schema/fail/parameter-object-header-allowReserved.yaml @@ -0,0 +1,11 @@ +openapi: 3.2.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 4122c75c61..d0487663cd 100644 --- a/tests/schema/pass/header-object-examples.yaml +++ b/tests/schema/pass/header-object-examples.yaml @@ -23,4 +23,3 @@ components: 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..ce5c5f58d7 --- /dev/null +++ b/tests/schema/pass/parameter-object-cookie-form-allowReserved.yaml @@ -0,0 +1,18 @@ +openapi: 3.2.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..5d394d901f --- /dev/null +++ b/tests/schema/pass/parameter-object-path-allowReserved.yaml @@ -0,0 +1,12 @@ +openapi: 3.2.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..237ece10eb --- /dev/null +++ b/tests/schema/pass/parameter-object-query-allowReserved.yaml @@ -0,0 +1,11 @@ +openapi: 3.2.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 7281c4a6cbc1b37f794b02f44fe36f3096ebf4fb Mon Sep 17 00:00:00 2001 From: Karen Etheridge Date: Sun, 23 Nov 2025 13:46:24 -0800 Subject: [PATCH 06/14] 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 | 21 ++++++++++++------- .../pass/parameter-object-examples.yaml | 12 +++++++---- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/schemas/validation/schema.yaml b/src/schemas/validation/schema.yaml index 5dcf44f44e..2f40e4b399 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: @@ -610,7 +616,6 @@ $defs: type: boolean allowReserved: type: boolean - default: false encoding: type: object additionalProperties: @@ -627,7 +632,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 +646,7 @@ $defs: properties: style: default: form - $ref: '#/$defs/styles-for-form' + $ref: '#/$defs/explode-for-form' $ref: '#/$defs/specification-extensions' unevaluatedProperties: false @@ -1127,13 +1135,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 8a3db655ba..51e917362f 100644 --- a/tests/schema/pass/parameter-object-examples.yaml +++ b/tests/schema/pass/parameter-object-examples.yaml @@ -9,21 +9,23 @@ paths: in: header description: token to be passed as a header required: true + explode: false schema: type: array items: type: integer format: int64 style: simple - - name: username + - name: usernames in: path - description: username to fetch + description: usernames to fetch required: true + explode: false schema: - type: string + type: array - name: id in: query - description: ID of the object to fetch + description: IDs of the object to fetch required: false schema: type: array @@ -55,10 +57,12 @@ paths: - in: cookie name: my_cookie1 style: form + explode: false schema: {} - in: cookie name: my_cookie2 style: cookie + explode: true schema: {} /user: parameters: From 48e7905861213f9968a39bd33989355348b59dac Mon Sep 17 00:00:00 2001 From: Karen Etheridge Date: Tue, 16 Dec 2025 14:59:23 -0800 Subject: [PATCH 07/14] 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) --- tests/schema/pass/style-defaults.yaml | 105 ++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 tests/schema/pass/style-defaults.yaml diff --git a/tests/schema/pass/style-defaults.yaml b/tests/schema/pass/style-defaults.yaml new file mode 100644 index 0000000000..823eac7d94 --- /dev/null +++ b/tests/schema/pass/style-defaults.yaml @@ -0,0 +1,105 @@ +openapi: 3.2.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 ccdba59c8082cf03a9a3945755a46afb64d69d54 Mon Sep 17 00:00:00 2001 From: Karen Etheridge Date: Sat, 24 Jan 2026 11:48:43 -0800 Subject: [PATCH 08/14] fix broken examples For the Appendix C.4 example, "words" is said to not explode its values. --- src/oas.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/oas.md b/src/oas.md index f43ed08843..2c3ab52385 100644 --- a/src/oas.md +++ b/src/oas.md @@ -1070,7 +1070,7 @@ examples: dataValue: page: 4 pageSize: 50 - serializeValue: page=4&pageSize=50 + serializedValue: page=4&pageSize=50 ``` A complex parameter using `content` to define serialization, with multiple levels and types of examples shown to make the example usage options clear — note that `dataValue` is the same at both levels and does not need to be shown in both places in normal usage, but `serializedValue` is different: @@ -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: @@ -4971,6 +4974,7 @@ parameters: type: array items: type: string + explode: false ``` This translates to the following URI Template: From a0ba52f11f26bf9cb7e1a3ae12e2dbcca16f91c6 Mon Sep 17 00:00:00 2001 From: Karen Etheridge Date: Sat, 15 Nov 2025 14:31:04 -0800 Subject: [PATCH 09/14] 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 2c3ab52385..83dad2d5a4 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 824abb4a3697fc62d52243fb2294a6da9d44f599 Mon Sep 17 00:00:00 2001 From: Karen Etheridge Date: Sat, 15 Nov 2025 14:31:04 -0800 Subject: [PATCH 10/14] specify how query parameters are added to the URL --- src/oas.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oas.md b/src/oas.md index 83dad2d5a4..2fc3eb1069 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. From c67d915eeee8882ea28a8b47a88dd70dec7059eb Mon Sep 17 00:00:00 2001 From: Valerii Petryniak <44531564+valerii15298@users.noreply.github.com> Date: Thu, 25 Dec 2025 01:51:23 +0200 Subject: [PATCH 11/14] Fix yaml formatting --- src/oas.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/oas.md b/src/oas.md index 2fc3eb1069..620bd04867 100644 --- a/src/oas.md +++ b/src/oas.md @@ -4452,8 +4452,7 @@ application/xml: - Some text - unit: cubits value: 42 - null - ] + - null externalValue: ./examples/OneTwoThree.xml ``` From 43b556b60c75a5229ff33ac96127806c18c0183d Mon Sep 17 00:00:00 2001 From: Valerii Petryniak <44531564+valerii15298@users.noreply.github.com> Date: Thu, 25 Dec 2025 01:41:47 +0200 Subject: [PATCH 12/14] Fix typo in HTTP Set-Cookie example --- src/oas.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oas.md b/src/oas.md index 620bd04867..86d4e9438a 100644 --- a/src/oas.md +++ b/src/oas.md @@ -2861,7 +2861,7 @@ components: In an HTTP message, the serialized example would look like: ```http -Set-Cookie: lang=en-US; Expires=Wed, 09 Jun 2021 10:18:14 GM +Set-Cookie: lang=en-US; Expires=Wed, 09 Jun 2021 10:18:14 GMT Set-Cookie: foo=bar; Expires=Wed, 09 Jun 2021 10:18:14 GMT Set-Cookie: urlSafeData=Hello%2C%20world%21 ``` From 32cbc2d2dd305e2b3dc86808bb250d73a8b33967 Mon Sep 17 00:00:00 2001 From: Valerii Petryniak <44531564+valerii15298@users.noreply.github.com> Date: Thu, 25 Dec 2025 01:35:00 +0200 Subject: [PATCH 13/14] Update section header from 'serializedExample' to 'serializedValue' --- src/oas.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oas.md b/src/oas.md index 86d4e9438a..293409eaac 100644 --- a/src/oas.md +++ b/src/oas.md @@ -2386,7 +2386,7 @@ The `serializedValue` and `externalValue` fields both MUST show the serialized f For Media Type Objects, this is a document of the appropriate media type, with any Encoding Object effects applied. For Parameter and Header Objects using `schema` and `style` rather than a Media Type Object, see [Style Examples](#style-examples) for what constitutes a serialized value. -##### Criteria for `serializedExample` +##### Criteria for `serializedValue` A serialization can be represented as a valid Unicode string in `serializedValue` if any of the following are true of the serialization: From f2c18be399a20878f38b6c2d658cfdf200dffedd Mon Sep 17 00:00:00 2001 From: Valerii Petryniak <44531564+valerii15298@users.noreply.github.com> Date: Thu, 25 Dec 2025 01:13:48 +0200 Subject: [PATCH 14/14] Fix typo in querystring formats section --- src/oas.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oas.md b/src/oas.md index 293409eaac..5148de6065 100644 --- a/src/oas.md +++ b/src/oas.md @@ -935,7 +935,7 @@ The following table shows serialized examples, as would be shown with the `seria #### Extending Support for Querystring Formats -Many frameworks define query string syntax for complex values, such as appending array indices to parameter names or indicating multiple levels of of nested objects, which go well beyond the capabilities of the `deepObject` style. +Many frameworks define query string syntax for complex values, such as appending array indices to parameter names or indicating multiple levels of nested objects, which go well beyond the capabilities of the `deepObject` style. As these are not standards, and often contradict each other, the OAS does not attempt to support them directly. Two avenues are available for supporting such formats with `in: "querystring"`: