-
Notifications
You must be signed in to change notification settings - Fork 9.1k
Allow discriminator to be optional #4339
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not totally on board with the naming of default
.
The definition is different from JSON Schema and what you are trying to accomplish here by specifying a schema instance to validate against vs the commonly, well used, instance value.
src: https://json-schema.org/draft/2020-12/json-schema-validation#section-9.2
There are no restrictions placed on the value of this keyword. When multiple occurrences of this keyword are applicable to a single sub-instance, implementations SHOULD remove duplicates.
This keyword can be used to supply a default JSON value associated with a particular schema. It is RECOMMENDED that a default value be valid against the associated schema.
The other concern I have is the referenced schemas in oneOf/anyOf may have all properties optional, there is no requirement to have at least one required property to satisfy a oneOf subschema. The only requirement is that the validation succeeds which can be accomplished with other means besides a property name.
@jeremyfiel |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a few minor edits for clarification
Co-authored-by: Jeremy Fiel <[email protected]>
I feel like this line should be updated with the language of This was not part of your changes, but it's related and the perfect time to make additional clarifications OpenAPI-Specification/src/oas.md Line 3459 in 7ebde14
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may be overkill to link all of the anchors, but I think that's how the spec usually does it. Feel free to ignore
There is one typo with the defaultMapping
naming that should be corrected if you choose to ignore the anchor links.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As problematic as the allOf
form is, I'm not sure I'm OK with removing the example entirely. People do use it, and we can't remove it in a minor version, and it's extremely hard to understand even with an example.
src/oas.md
Outdated
| <a name="discriminator-mapping"></a> mapping | Map[`string`, `string`] | An object to hold mappings between payload values and schema names or URI references. | | ||
| <a name="default"></a> defaultMapping | `string` | The schema name or URI reference to a schema that is expected to validate the structure of the model when the discriminating property is not present in the payload. | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name defaultMapping
suggests to me that this is the default whenever there isn't a defined mapping. So not just when the property is missing, but when the property has a value that cannot otherwise be resolved. Is this the intention? If not, I'd suggest a name tying to absence rather than "default."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was not the intention. But it is an interesting idea. This could be accomplished with a slightly different schema for the defaultMapping. Instead of not: required: ['petType']
it could be:
properties:
petType:
not:
enum: ['dog', 'cat']
This might get unwieldy for a schema with many variants, but there is some attractiveness to this.
Thoughts?
I pushed some commits that address most of the outstanding comments. I made musts and mays uppercase. I added the language @handrews suggested about how discriminating values are used for I fixed the instance where I did not make every instance of "Discriminator Object" into a link. When there were multiple occurrences of Discriminator Object in a section, I made the first one a link and left the rest as plain text. I think other "Object" types are handled similarly -- for example only 13 of the 20 occurrences of "Path Item Object" are links, the rest are plain text. I left open the question about the name |
Co-authored-by: Jeremy Fiel <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid "MUST" and "MAY" in Examples section
Co-authored-by: Ralf Handl <[email protected]>
I think the changes you wanted were made, so I'll dismiss your review to unblock this PR
We'll wait until we can get input from @handrews on this one. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Thanks for the refinements.
I think this was ready to go except waiting on me so I'll go ahead and merge it. |
|
||
###### Models with Polymorphism Support using allOf and a Discriminator Object | ||
|
||
It is also possible to describe polymorphic models using `allOf`. The following example uses `allOf` with a [Discriminator Object](#discriminator-object) to describe a polymorphic `Pet` model. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it valid (but duplicate) or illegal to also add a oneOf
in Pet too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is covered in the example just above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do mean the combination of oneOf
in Pet
and allOf
in Cat
:
components:
schemas:
Pet:
type: object
discriminator:
propertyName: petType
properties:
name:
type: string
petType:
type: string
required:
- name
- petType
oneOf:
- $ref: '#/components/schemas/Cat'
- $ref: '#/components/schemas/Dog'
Cat: # "Cat" will be used as the discriminating value
description: A representation of a cat
allOf:
- $ref: '#/components/schemas/Pet'
- type: object
properties:
huntingSkill:
type: string
description: The measured skill for hunting
enum:
- clueless
- lazy
- adventurous
- aggressive
required:
- huntingSkill
Dog: # "Dog" will be used as the discriminating value
description: A representation of a dog
allOf:
- $ref: '#/components/schemas/Pet'
- type: object
properties:
packSize:
type: integer
format: int32
description: the size of the pack the dog is from
default: 0
minimum: 0
required:
- packSize
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hfhbd no, that is not valid in terms of JSON Schema (and therefore also invalid OAS).
The reason is that this creates a cyclic reference that cannot be disambiguated by runtime evaluation.
You can see this because allOf
and oneOf
are examples of an in-place applicator: They apply one or more sub-schemas to the same instance location. JSON Schema implementations are required to detect infinite loops that occur when you revisit the same schema object twice without having changed instance location, which is what happens here. Let me know if that is not clear enough and I can explain further.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your helpful answer and clarification!
This PR changes the
discriminator
to allow the discriminator property to be an optional field, so that when it is not present thedefault
field can be used to specify which schema of theanyOf
oroneOf
is expected to validate the structure of the model.I've also massaged the descriptions of polymorphism to emphasize that JSON Schema can and should be used to describe polymorphism and that discriminator is an optional extension of that support.
I also dropped some of the JSON examples when the same example was shown in yaml just to cut down on redundancy.
Tick one of the following options: