From 4c046ad6ecdee5879eb9c8e53815c1a609efcbca Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Fri, 6 Jun 2025 13:06:22 -0700 Subject: [PATCH 1/7] Explain Param/Header/Enc example serialization The rules for this have not been clear, and are not always intuitive. This states and explains them directly and ensures that the Style Examples table matches the rules. --- src/oas.md | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/oas.md b/src/oas.md index 3df5572368..16dc7eb46a 100644 --- a/src/oas.md +++ b/src/oas.md @@ -1026,9 +1026,23 @@ In order to support common ways of serializing simple parameters, a set of `styl See [Appendix E](#appendix-e-percent-encoding-and-form-media-types) for a discussion of percent-encoding, including when delimiters need to be percent-encoded and options for handling collisions with percent-encoded data. +##### Serialization and Examples + +When showing serialized examples, such as with the [Example Object's](#example-object) `serializedValue` or `externalSerializedValue` fields, in most cases the value to show is the value, with all relevant percent-encoding or other encoding/escaping mechanisms, and also including any delimiters produced by the `style` and `explode` configuration. + +For query parameters (`in: "query"` and `in: "querystring"`) and cookies (`in: "cookie"`), the parameter names MUST also be shown, as they are determined in part by `style` and `explode` rather than only by `name`, and the leading `?` or `&` delimiter MUST NOT be shown, as it is not used in all scenarios. + +In particular, these fields are also used in the [Encoding Object](#encoding-object) for `application/x-www-form-urlencoded` request bodies which do not use a leading `?` as that delimiter is part of the URI syntax. +Within URIs, whether each parameter is preceded by the `?` or a `&` is determined by its position relative to other parameters, and may not always be the same for a Parameter Object that is referenced by multiple Operations. +For cookies, neither the `?` nor `&` delimiter is correct (see [Appendix D: Serializing Headers and Cookies](#appendix-d-serializing-headers-and-cookies) for more details). + +Note that RFC6570 form expansion implementations will include either a leading `?` or `&` delimiter, depending on which type of form expansion is used, so in some scenarios it is necessary to strip off or change the leading delimiter. + +The following section illustrates these rules. + ##### Style Examples -Assume a parameter named `color` has one of the following values: +Assume a parameter named `color` has one of the following values, where the value to the right of the `->` is what would be shown in the `dataValue` field of an Example Object: ```js string -> "blue" @@ -1036,13 +1050,12 @@ Assume a parameter named `color` has one of the following values: object -> { "R": 100, "G": 200, "B": 150 } ``` -The following table shows examples, as would be shown with the `example` or `examples` keywords, of the different serializations for each value. +The following table shows serialized examples, as would be shown with the `serializedValue` field of an Example Object, of the different serializations for each value. * The value _empty_ denotes the empty string, and is unrelated to the `allowEmptyValue` field * The behavior of combinations marked _n/a_ is undefined * The `undefined` column replaces the `empty` column in previous versions of this specification in order to better align with [RFC6570](https://www.rfc-editor.org/rfc/rfc6570.html#section-2.3) terminology, which describes certain values including but not limited to `null` as "undefined" values with special handling; notably, the empty string is _not_ undefined -* For `form` and the non-RFC6570 query string styles `spaceDelimited`, `pipeDelimited`, and `deepObject`, each example is shown prefixed with `?` as if it were the only query parameter; see [Appendix C](#appendix-c-using-rfc6570-based-serialization) for more information on constructing query strings from multiple parameters, and [Appendix D](#appendix-d-serializing-headers-and-cookies) for warnings regarding `form` and cookie parameters -* Note that the `?` prefix is not appropriate for serializing `application/x-www-form-urlencoded` HTTP message bodies, and MUST be stripped or (if constructing the string manually) not added when used in that context; see the [Encoding Object](#encoding-object) for more information +* For `form` and the non-RFC6570 query string styles `spaceDelimited`, `pipeDelimited`, and `deepObject`, see [Appendix C](#appendix-c-using-rfc6570-based-serialization) for more information on constructing query strings from multiple parameters, and [Appendix D](#appendix-d-serializing-headers-and-cookies) for warnings regarding `form` and cookie parameters * The examples are percent-encoded as required by RFC6570 and RFC3986; see [Appendix E](#appendix-e-percent-encoding-and-form-media-types) for a thorough discussion of percent-encoding concerns, including why unencoded `|` (`%7C`), `[` (`%5B`), and `]` (`%5D`) seem to work in some environments despite not being compliant. | [`style`](#style-values) | `explode` | `undefined` | `string` | `array` | `object` | @@ -1053,14 +1066,14 @@ The following table shows examples, as would be shown with the `example` or `exa | label | true | . | .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 | false | _n/a_ | _n/a_ | _n/a_ | _n/a_ | -| deepObject | true | _n/a_ | _n/a_ | _n/a_ | ?color%5BR%5D=100&color%5BG%5D=200&color%5BB%5D=150 | +| deepObject | true | _n/a_ | _n/a_ | _n/a_ | color%5BR%5D=100&color%5BG%5D=200&color%5BB%5D=150 | ##### Extending Support for Querystring Formats From 824c49042eea4640d5232dee59fcbf09c1d71bd3 Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Mon, 9 Jun 2025 10:54:37 -0700 Subject: [PATCH 2/7] Parameter Object example updates --- src/oas.md | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/src/oas.md b/src/oas.md index 16dc7eb46a..42983139a8 100644 --- a/src/oas.md +++ b/src/oas.md @@ -1100,6 +1100,10 @@ schema: type: integer format: int64 style: simple +examples: + number: + dataValue: [12345678, 90099] + serializedValue: "12345678,90099" ``` A path parameter of a string value: @@ -1111,6 +1115,13 @@ description: username to fetch required: true schema: type: string +examples: + "Edsger Dijkstra": + dataValue: edijkstra + serializedValue: edijkstra + Diṅnāga: + dataValue: diṅnāga + serializedValue: di%E1%B9%85n%C4%81ga ``` An optional query parameter of a string value, allowing multiple values by repeating the query parameter: @@ -1126,9 +1137,13 @@ schema: type: string style: form explode: true +examples: + stuff: + dataValue: [this, that, theother] + serializedValue: id=this&id=that&id=theother ``` -A free-form query parameter, allowing undefined parameters of a specific type: +A free-form query parameter, allowing undefined parameters of a `type: "string"`: ```yaml in: query @@ -1136,8 +1151,12 @@ name: freeForm schema: type: object additionalProperties: - type: integer + type: string style: form +examples: + freeForm: + dataValue: {"yeah": "I'm", "free": "forming"} + serializedValue: yeah=I%27m&free=forming ``` A complex parameter using `content` to define serialization: @@ -1170,13 +1189,17 @@ content: # Allow an arbitrary JSON object to keep # the example simple type: object - example: { - "numbers": [1, 2], - "flag": null - } + examples: + minimized: + summary: JSON should be serialized with minimal whitespace + dataValue: { + "numbers": [1, 2], + "flag": null + } + serializedValue: '{"numbers":[1,2],"flag":null}' ``` -Assuming a path of `/foo`, a server of `https://example.com`, the full URL incorporating the value from the `example` field (with whitespace minimized) would be: +Assuming a path of `/foo`, a server of `https://example.com`, the full URL incorporating the value from the `serializedValue` field would be: ```uri https://example.com/foo?%7B%22numbers%22%3A%5B1%2C2%5D%2C%22flag%22%3Anull%7D @@ -1191,12 +1214,14 @@ content: application/jsonpath: schema: type: string - example: $.a.b[1:1] + examples: + simpleSelector: + dataValue: $.a.b[1:1] ``` As there is not, as of this writing, a [registered](#media-type-registry) mapping between the JSON Schema data model and JSONPath, the details of the string's allowed structure would need to be conveyed either in a human-readable `description` field, or through a mechanism outside of the OpenAPI Description, such as a JSON Schema for the data structure to be queried. -Assuming a path of `/foo` and a server of `https://example.com`, the full URL incorporating the value from the `example` field would be: +Assuming a path of `/foo` and a server of `https://example.com`, the full URL incorporating the value from the `dataValue` field would be: ```uri https://example.com/foo?%24.a.b%5B1%3A1%5D From dbf07e170e2a2746b240071ecef62d4a9faeb456 Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Mon, 9 Jun 2025 11:00:34 -0700 Subject: [PATCH 3/7] Header Object example updates --- src/oas.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/oas.md b/src/oas.md index 42983139a8..84e02cbe49 100644 --- a/src/oas.md +++ b/src/oas.md @@ -2495,6 +2495,10 @@ X-Rate-Limit-Limit: description: The number of allowed requests in the current period schema: type: integer + examples: + OneHundred: + dataValue: 100 + serializedValue: "100" ``` Requiring that a strong `ETag` header (with a value starting with `"` rather than `W/`) is present. Note the use of `content`, because using `schema` and `style` would require the `"` to be percent-encoded as `%22`: From f7f869bd8c3f9806ac4cd80990b9e277b10e15d5 Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Tue, 10 Jun 2025 11:49:19 -0700 Subject: [PATCH 4/7] Add a more complex header example --- src/oas.md | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/oas.md b/src/oas.md index 84e02cbe49..0cabfdd32f 100644 --- a/src/oas.md +++ b/src/oas.md @@ -2486,7 +2486,7 @@ Using `content` with a `text/plain` media type is RECOMMENDED for headers where | ---- | :----: | ---- | | content | Map[`string`, [Media Type Object](#media-type-object)] | A map containing the representations for the header. The key is the media type and the value describes it. The map MUST only contain one entry. | -##### Header Object Example +##### Header Object Examples A simple header of type `integer`: @@ -2513,6 +2513,38 @@ ETag: pattern: ^" ``` +A `Link` header that, if present, must include links with the standard relation types `self`, `first`, `prev`, `next`, and `last`, as might be used on a paginated collection: + +```yaml +Link: + schema: + type: array + uniqueItems: true + minItems: 5 + maxItems: 5 + items: + type: string + anyOf: + - pattern: rel="?first"? + - pattern: rel="?prev"? + - pattern: rel="?self"? + - pattern: rel="?next"? + - pattern: rel="?last"? + style: simple + examples: + CollectionLinks: + dataValue: + - https://example.com/foos?page=1; rel=first + - https://example.com/foos?page=4; rel=prev + - https://example.com/foos?page=5; rel=self + - https://example.com/foos?page=6; rel=next + - https://example.com/foos?page=10; rel=last + serializedValue: https://example.com/foos?page=1; rel=first, https://example.com/foos?page=4; rel=prev, https://example.com/foos?page=5; rel=self, https://example.com/foos?page=6; rel=next, https://example.com/foos?page=10; rel=last +``` + +Note that the `items`, `uniqueItems: true`, and `anyOf` combination allows the links to appear in any order. +If a fixed order is desired, then `prefixItems` could be used and `uniqueItems` would not be necessary. + #### Tag Object Adds metadata to a single tag that is used by the [Operation Object](#operation-object). From 7830a6e113cfbab388cad71ce6e30e93af12378a Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Tue, 10 Jun 2025 12:04:55 -0700 Subject: [PATCH 5/7] Link example needs allowReserved: true --- src/oas.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/oas.md b/src/oas.md index 0cabfdd32f..06ebfc84fa 100644 --- a/src/oas.md +++ b/src/oas.md @@ -2531,6 +2531,10 @@ Link: - pattern: rel="?next"? - pattern: rel="?last"? style: simple + # The ";" character and the URI delimiters are reserved + # but needs to be allowed as headers do not expect these + # to be percent-encoded. + allowReserved: true examples: CollectionLinks: dataValue: From ac96d1ea2a522888ac95fb23ea2cf14256176f74 Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Mon, 9 Jun 2025 11:00:04 -0700 Subject: [PATCH 6/7] Response Object example updates These updates are about header usage in the Response Object. --- src/oas.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/oas.md b/src/oas.md index 06ebfc84fa..a3a0344ed9 100644 --- a/src/oas.md +++ b/src/oas.md @@ -2010,14 +2010,26 @@ headers: description: The number of allowed requests in the current period schema: type: integer + examples: + allowTen: + dataValue: 10 + serializedValue: '10' X-Rate-Limit-Remaining: description: The number of remaining requests in the current period schema: type: integer + examples: + twoRemaining: + dataValue: 2 + serializedValue: '2' X-Rate-Limit-Reset: description: The number of seconds left in the current period schema: type: integer + examples: + oneMinute: + dataValue: 60 + serializedValue: '60' ``` Response with no return value: From 68bfa301f3f30e67fa244136166116fc40fe8dd6 Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Tue, 10 Jun 2025 23:49:20 -0700 Subject: [PATCH 7/7] Better implementation of Link Actually ensure each pattern is matched - in the previous way the example was written, the uniqueItems was not sufficient as a link with the same rel but different URI would have satisfied the conditions. Also, the text says "includes" these rels, so there could be more entries. --- src/oas.md | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/oas.md b/src/oas.md index a3a0344ed9..45efc0f97a 100644 --- a/src/oas.md +++ b/src/oas.md @@ -2531,17 +2531,19 @@ A `Link` header that, if present, must include links with the standard relation Link: schema: type: array - uniqueItems: true - minItems: 5 - maxItems: 5 items: type: string - anyOf: - - pattern: rel="?first"? - - pattern: rel="?prev"? - - pattern: rel="?self"? - - pattern: rel="?next"? - - pattern: rel="?last"? + allOf: + - contains: + pattern: rel="?first"? + - contains: + pattern: rel="?prev"? + - contains: + pattern: rel="?self"? + - contains: + pattern: rel="?next"? + - contains: + pattern: rel="?last"? style: simple # The ";" character and the URI delimiters are reserved # but needs to be allowed as headers do not expect these @@ -2558,8 +2560,8 @@ Link: serializedValue: https://example.com/foos?page=1; rel=first, https://example.com/foos?page=4; rel=prev, https://example.com/foos?page=5; rel=self, https://example.com/foos?page=6; rel=next, https://example.com/foos?page=10; rel=last ``` -Note that the `items`, `uniqueItems: true`, and `anyOf` combination allows the links to appear in any order. -If a fixed order is desired, then `prefixItems` could be used and `uniqueItems` would not be necessary. +Note that the `allOf` with `contains` combination allows the links to appear in any order. +If a fixed order is desired, then `prefixItems` could be used and the `allof` would not be necessary. #### Tag Object