Skip to content

documented the discriminator property #1093

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

Merged
merged 5 commits into from
May 19, 2017
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions versions/3.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -3012,6 +3012,125 @@ schemas:
- packSize
```

#### <a name="discriminatorObject"></a>Discriminator Object
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest renaming this anchor as discriminatorProperty / Discriminator Property so that OAS only uses "Object" when referring to a JSON object.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The discriminator object described here actually is a JSON (or YAML) object in the API definition (In OpenAPI 2.0 it was a simple string), though it describes a single (string) property of the JSON payload.

I would say the name is fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DavidBiesack you are correct. Using title is a bad idea, and I've disallowed inline schemas for consideration with the discriminator.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, Tony


When request bodies or response payloads may be one of a number of different schemas, a `discriminator` property can be used to aid in serialization, deserialization, and validation. The discriminator is a specific property in an object which is used to inform the consumer of the specification of an alternative schema based on the value associated with it.

##### Fixed Fields
Field Name | Type | Description
---|:---:|---
<a name="propertyName"></a>propertyName | `string` | **required** the name of the property in the payload that will hold the discriminator value.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The examples are using property, here it is propertyName.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, will fix

<a name="discriminatorMapping"></a> mapping | Map[`string`, `string`] | An object to hold mappings between payload values and schema names or references.

The discriminator attribute is legal only when using one of the composite keywords `oneOf`, `anyOf`, `allOf`.

In OAS 3.0, a response payload may be described to be exactly one of any number of types:

```
MyResponseType:
oneOf:
- $ref: '#/components/schemas/Cat'
- $ref: '#/components/schemas/Dog'
- $ref: '#/components/schemas/Lizard'
```

which means the paylod _must_, by validation, match exactly one of the schemas described by `Cat`, `Dog`, or `Lizard`. In this case, a discriminator will act as a "hint" to bypass validation and selection of the matching schema which may be a costly operation, depending on the complexity of the schema. We can then describe exactly which field tells us which schema to use:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure "bypass validation" is the right phrase here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I'll rephrase. will ==> may, bypass ==> shortcut



```
MyResponseType:
oneOf:
- $ref: '#/components/schemas/Cat'
- $ref: '#/components/schemas/Dog'
- $ref: '#/components/schemas/Lizard'
discriminator:
property: pet_type
```

The expectation now is that a property with name `pet_type` _must_ be present in the response payload, and the value will correspond to the name of a schema defined in the OAS document. Thus the response payload:

```
{
"id": 12345,
"pet_type": "Cat"
}
```

Will indicate that the `Cat` schema be used in conjunction with this payload.

In scenarios where the value of the discriminator field does not match the schema name, an optional `mapping` definition may be used:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if the discriminator value does not match a schema or mapping? We should probably document this as it will impact tooling.


```
MyResponseType:
oneOf:
- $ref: '#/components/schemas/Cat'
- $ref: '#/components/schemas/Dog'
- $ref: '#/components/schemas/Lizard'
discriminator:
property: pet_type
mapping:
cat: '#/components/schemas/Cat'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be

      cachorro: '#/components/schemas/Dog'

(introducing cat is confusing since the above example used "pet_type": "Cat")

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DavidBiesack you are correct, I will update the example.

```

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 composing the parent schema in an `allOf` construct may be used as an alternate schema.

For example:

```
components:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove components: and schemas: here since they are not used in the other examples.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I believe the components/schemas is important here, since we're showing references inside the example. I'll ensure the composition examples are consistent.

schemas:
Pet:
type: object
required:
- pet_type
properties:
pet_type:
type: string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding an enum for this as well, to allow for validation:

         pet_type:
           type: string
           enum:
             - Cat
             - cachorro

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would defeat the goal of this example--here, we're showing that the parent object Pet does not have knowledge of all of the composed types. Thus, any object which extends Pet with the allOf construct is a candidate for use

discriminator:
propertyName: pet_type
mapping:
cachorro: Dog
Cat:
allOf:
- $ref: '#/components/schemas/Pet'
- type: object
# all other properties specific to a `Cat`
properties:
name:
type: string
Dog:
allOf:
- $ref: '#/components/schemas/Pet'
- type: object
# all other properties specific to a `Dog`
properties:
bark:
type: string
```

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding Lizard: here to be consistent with the previous example.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, I think Lizards are cool

a payload like this:

```
{
"pet_type": "Cat",
"name": "misty"
}
```

will indicate that the `Cat` schema be used. Likewise this schema:

```
{
"pet_type": "cachorro",
"bark": "soft"
}
```

will map to `Dog` because of the definition in the `mappings` element.


Copy link
Contributor

@DavidBiesack DavidBiesack May 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest also adding a note:

Some OpenAPI definitions use external, reusable schema references such as

      properties:
        pet_type:
           type: string
           enum:
             - cat
             - cachorro
             - lizard
      oneOf:
      - $ref: 'http://www.example.com/schemas/Cat/schema.json'
      - $ref: 'http://www.example.com/schemas/Doc/schema.json'
      - $ref: 'http://www.example.com/schemas/Lizard/schema.json'
      discriminator:
        propertyName: pet_type
        mapping:
          cat: 'http://www.example.com/schemas/Cat/schema.json'
          cachorro: 'http://www.example.com/schemas/Doc/schema.json'
          lizard: 'http://www.example.com/schemas/Lizard/schema.json'

and an implicit name mapping based on schema names is not possible.
For such cases, a mapping is required.

The above $ref values are JSON Schema files, not OpenAPI documents. Schema may
also be referenced from schema definitions from an external OpenAPI definition:

      properties:
        pet_type:
           type: string
           enum:
             - cat
             - cachorro
             - lizard
      oneOf:
      - $ref: 'http://www.example.com/library.json#/components/schema/Cat.json'
      - $ref: 'http://www.example.com/library.json#/components/schema/Doc.json'
      - $ref: 'http://www.example.com/library.json#/components/schema/Lizard.json'
      discriminator:
        propertyName: pet_type
        mapping:
          cat: $ref: 'http://www.example.com/library.json#/components/schema/Cat.json'
          cachorro: $ref: 'http://www.example.com/library.json#/components/schema/Doc.json'
          lizard: $ref: 'http://www.example.com/library.json#/components/schema/Lizard.json'

[in particular, citing external JSON Schema, and not just #/definitions/SchemaName from other OpenAPI 2.0 documents, worked in 2.0 and we need to ensure this still works in 3.0, whether this involves discriminators or not.]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, I'll add language around this 👍

#### <a name="xmlObject"></a>XML Object

A metadata object that allows for more fine-tuned XML model definitions.
Expand Down