From 7e3b58bb53db34cb8a10a2705c28020282eeb71e Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Sun, 19 May 2024 11:42:51 -0700 Subject: [PATCH 1/4] Clarify discriminator + oneOf/anyOf/allOf usage (3.0.4) This moves some guidance up to the fixed fields section where it is more obvious, and explicitly designates other configurations as having undefined behavior. --- versions/3.0.4.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/versions/3.0.4.md b/versions/3.0.4.md index b125dab467..1707fe8059 100644 --- a/versions/3.0.4.md +++ b/versions/3.0.4.md @@ -2744,7 +2744,11 @@ Field Name | Type | Description propertyName | `string` | **REQUIRED**. The name of the property in the payload that will hold the discriminator value. mapping | Map[`string`, `string`] | An object to hold mappings between payload values and schema names or references. -The discriminator object is legal only when using one of the composite keywords `oneOf`, `anyOf`, `allOf`. Note that because the discriminating property's value is used as a component name and/or as the key in the `mapping` object, the behavior of any value that is not a string is undefined. +The discriminator object is legal only when using one of the composite keywords `oneOf`, `anyOf`, `allOf`. +In both the `oneOf` and `anyOf` use cases, where those keywords are adjacent to `discriminator`, all possible schemas MUST be listed explicitly. +To avoid redundancy, the discriminator MAY be added to a parent schema definition, and all schemas comprising the parent schema in an `allOf` construct may be used as an alternate schema. +The behavior of any other configuration of `oneOf`, `anyOf`, `allOf` and `discriminator` is undefined. +Note also that because the discriminating property's value is used as a component name and/or as the key in the `mapping` object, the behavior of any value that is not a string is undefined. In OAS 3.0, a response payload MAY be described to be exactly one of any number of types: @@ -2800,9 +2804,7 @@ Here the discriminator _value_ of `dog` will map to the schema `#/components/sch When used in conjunction with the `anyOf` construct, the use of the discriminator can avoid ambiguity where multiple schemas may satisfy a single payload. -In both the `oneOf` and `anyOf` use cases, all possible schemas MUST be listed explicitly. To avoid redundancy, the discriminator MAY be added to a parent schema definition, and all schemas comprising the parent schema in an `allOf` construct may be used as an alternate schema. - -For example: +This example shows the `allOf` usage, which avoids needing to reference all child schemas in the parent: ```yaml components: From 0bb754129f3e84d44fe85303f372efc9d0de453a Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Mon, 20 May 2024 17:43:54 -0700 Subject: [PATCH 2/4] More discriminator guidance consolidation This creates subsections to organize the different topics, pulls key guidance out of the examples and up into those sections, and provides clarification on the ambiguity of names and URIs. --- versions/3.0.4.md | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/versions/3.0.4.md b/versions/3.0.4.md index 1707fe8059..e8f384cc71 100644 --- a/versions/3.0.4.md +++ b/versions/3.0.4.md @@ -2734,21 +2734,35 @@ components: #### Discriminator Object -When request bodies or response payloads may be one of a number of different schemas, a `discriminator` object can be used to aid in serialization, deserialization, and validation. The discriminator is a specific object in a schema which is used to inform the consumer of the specification of an alternative schema based on the value associated with it. - -When using the discriminator, _inline_ schemas will not be considered. +When request bodies or response payloads may be one of a number of different schemas, a Discriminator Object can be used to aid in serialization, deserialization, and validation. +It does this by implicitly or explicitly associating the possible values of a named property with alternative schemas. ##### Fixed Fields Field Name | Type | Description ---|:---:|--- propertyName | `string` | **REQUIRED**. The name of the property in the payload that will hold the discriminator value. - mapping | Map[`string`, `string`] | An object to hold mappings between payload values and schema names or references. + mapping | Map[`string`, `string`] | An object to hold mappings between payload values and schema names or URI references. -The discriminator object is legal only when using one of the composite keywords `oneOf`, `anyOf`, `allOf`. +##### Conditions for Using the Discriminator Object +The Discriminator Object is legal only when using one of the composite keywords `oneOf`, `anyOf`, `allOf`. In both the `oneOf` and `anyOf` use cases, where those keywords are adjacent to `discriminator`, all possible schemas MUST be listed explicitly. To avoid redundancy, the discriminator MAY be added to a parent schema definition, and all schemas comprising the parent schema in an `allOf` construct may be used as an alternate schema. -The behavior of any other configuration of `oneOf`, `anyOf`, `allOf` and `discriminator` is undefined. -Note also that because the discriminating property's value is used as a component name and/or as the key in the `mapping` object, the behavior of any value that is not a string is undefined. +It is implementation-defined as to whether all named [Schema Objects](#schemaObject) under the [Components Object](#componentsObject), or only those that are otherwise directly referenced are searched for matching `allOf` references. +However, it is RECOMMENDED to search all named schemas in the Components Object because it is common with the `allOf` usage for other parts of the API to only directly reference the parent schema (that contains the `discriminator`). + +The behavior of any configuration of `oneOf`, `anyOf`, `allOf` and `discriminator` that is not described above is undefined. + +##### Options for Mapping Values to Schemas +The value of the property named in `propertyName` is is used as the name of the associated schema under the [Components Object](#componentsObject), _unless_ a `mapping` is present for that value. +The `mapping` entry maps a specific property value to either a different schema component name, or to a schema identified by a URI. +When using implicit or explicit schema component names, inline `oneOf` or `anyOf` subschemas are not considered. +The behavior of a `mapping` value that is both a valid schema name and a valid relative URI reference is implementation-defined, but it is RECOMMENDED that it be treated as a schema name. +To ensure that an ambiguous value (e.g. `"foo"`) is treated as a relative URI reference by all implementations, authors MUST prefix it with the `"."` path segment (e.g. `"./foo"`). + +Mapping keys MUST be string values, but tooling MAY convert response values to strings for comparison. +However, the exact nature of such conversions are implementation-defined. + +##### Examples In OAS 3.0, a response payload MAY be described to be exactly one of any number of types: @@ -2800,7 +2814,7 @@ MyResponseType: monster: https://gigantic-server.com/schemas/Monster/schema.json ``` -Here the discriminator _value_ of `dog` will map to the schema `#/components/schemas/Dog`, rather than the default (implicit) value of `Dog`. If the discriminator _value_ does not match an implicit or explicit mapping, no schema can be determined and validation SHOULD fail. Mapping keys MUST be string values, but tooling MAY convert response values to strings for comparison. +Here the discriminator _value_ of `dog` will map to the schema `#/components/schemas/Dog`, rather than the default (implicit) value of `Dog`. If the discriminator _value_ does not match an implicit or explicit mapping, no schema can be determined and validation SHOULD fail. When used in conjunction with the `anyOf` construct, the use of the discriminator can avoid ambiguity where multiple schemas may satisfy a single payload. From 63d56f549670644d613e4d0bb04f8bc9248a821e Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Mon, 20 May 2024 21:06:58 -0700 Subject: [PATCH 3/4] More wording improvements for discriminator. --- versions/3.0.4.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/versions/3.0.4.md b/versions/3.0.4.md index e8f384cc71..25a71d0b5c 100644 --- a/versions/3.0.4.md +++ b/versions/3.0.4.md @@ -2734,8 +2734,7 @@ components: #### Discriminator Object -When request bodies or response payloads may be one of a number of different schemas, a Discriminator Object can be used to aid in serialization, deserialization, and validation. -It does this by implicitly or explicitly associating the possible values of a named property with alternative schemas. +When request bodies or response payloads may be one of a number of different schemas, a Discriminator Object can be used to aid in serialization, deserialization, and validation by implicitly or explicitly associating the possible values of a named property with alternative schemas. ##### Fixed Fields Field Name | Type | Description @@ -2746,9 +2745,9 @@ Field Name | Type | Description ##### Conditions for Using the Discriminator Object The Discriminator Object is legal only when using one of the composite keywords `oneOf`, `anyOf`, `allOf`. In both the `oneOf` and `anyOf` use cases, where those keywords are adjacent to `discriminator`, all possible schemas MUST be listed explicitly. -To avoid redundancy, the discriminator MAY be added to a parent schema definition, and all schemas comprising the parent schema in an `allOf` construct may be used as an alternate schema. -It is implementation-defined as to whether all named [Schema Objects](#schemaObject) under the [Components Object](#componentsObject), or only those that are otherwise directly referenced are searched for matching `allOf` references. -However, it is RECOMMENDED to search all named schemas in the Components Object because it is common with the `allOf` usage for other parts of the API to only directly reference the parent schema (that contains the `discriminator`). +To avoid redundancy, the discriminator MAY be added to a parent schema definition, and all schemas building on the parent schema via an `allOf` construct may be used as an alternate schema. +It is implementation-defined as to whether all named [Schema Objects](#schemaObject) under the [Components Object](#componentsObject), or only those that are otherwise directly referenced are searched for `allOf` references to the parent schema. +However, it is RECOMMENDED to search all named schemas in the Components Object because it is common with the `allOf` usage for other parts of the API to only directly reference the parent schema. The behavior of any configuration of `oneOf`, `anyOf`, `allOf` and `discriminator` that is not described above is undefined. From 4a46b20c451de02e5dee9974fbcbb9be24098d10 Mon Sep 17 00:00:00 2001 From: Henry Andrews Date: Thu, 23 May 2024 09:17:22 -0700 Subject: [PATCH 4/4] Only one "is" is necessary (review feedback) Co-authored-by: Mike Kistler --- versions/3.0.4.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versions/3.0.4.md b/versions/3.0.4.md index 25a71d0b5c..1f10f510ef 100644 --- a/versions/3.0.4.md +++ b/versions/3.0.4.md @@ -2752,7 +2752,7 @@ However, it is RECOMMENDED to search all named schemas in the Components Object The behavior of any configuration of `oneOf`, `anyOf`, `allOf` and `discriminator` that is not described above is undefined. ##### Options for Mapping Values to Schemas -The value of the property named in `propertyName` is is used as the name of the associated schema under the [Components Object](#componentsObject), _unless_ a `mapping` is present for that value. +The value of the property named in `propertyName` is used as the name of the associated schema under the [Components Object](#componentsObject), _unless_ a `mapping` is present for that value. The `mapping` entry maps a specific property value to either a different schema component name, or to a schema identified by a URI. When using implicit or explicit schema component names, inline `oneOf` or `anyOf` subschemas are not considered. The behavior of a `mapping` value that is both a valid schema name and a valid relative URI reference is implementation-defined, but it is RECOMMENDED that it be treated as a schema name.