Skip to content

Inheritance and Polymorphism

Model Composition

In your API, you may have model schemas that share common properties. Instead of describing these properties for each schema repeatedly, you can describe the schemas as a composition of the common property set and schema-specific properties. In OpenAPI version 3, you do this with the allOf keyword:

1
components:
2
schemas:
3
BasicErrorModel:
4
type: object
5
required:
6
- message
7
- code
8
properties:
9
message:
10
type: string
11
code:
12
type: integer
13
minimum: 100
14
maximum: 600
15
ExtendedErrorModel:
16
allOf: # Combines the BasicErrorModel and the inline model
17
- $ref: "#/components/schemas/BasicErrorModel"
18
- type: object
19
required:
20
- rootCause
21
properties:
22
rootCause:
23
type: string

In the example above, the ExtendedErrorModel schema includes its own properties and properties inherited from BasicErrorModel. Note: When validating the data, servers and clients will validate the combined model against each model it consists of. It is recommended to avoid using conflicting properties (like properties that have the same names, but different data types).

Polymorphism

In your API, you can have request and responses that can be described by several alternative schemas. In OpenAPI 3.0, to describe such a model, you can use the oneOf or anyOf keywords:

1
components:
2
responses:
3
sampleObjectResponse:
4
content:
5
application/json:
6
schema:
7
oneOf:
8
- $ref: '#/components/schemas/simpleObject'
9
- $ref: '#/components/schemas/complexObject'
10
11
components:
12
schemas:
13
simpleObject:
14
15
complexObject:
16

In this example, the response payload can contain either simpleObject, or complexObject.

Discriminator

To help API consumers detect the object type, you can add the discriminator/propertyName keyword to model definitions. This keyword points to the property that specifies the data type name:

1
components:
2
responses:
3
sampleObjectResponse:
4
content:
5
application/json:
6
schema:
7
oneOf:
8
- $ref: '#/components/schemas/simpleObject'
9
- $ref: '#/components/schemas/complexObject'
10
discriminator:
11
propertyName: objectType
12
13
schemas:
14
simpleObject:
15
type: object
16
required:
17
- objectType
18
properties:
19
objectType:
20
type: string
21
22
complexObject:
23
type: object
24
required:
25
- objectType
26
properties:
27
objectType:
28
type: string
29

In our example, the discriminator points to the objectType property that contains the data type name. The discriminator is used with anyOf or oneOf keywords only. It is important that all the models mentioned below anyOf or oneOf contain the property that the discriminator specifies. This means, for example, that in our code above, both simpleObject and complexObject must have the objectType property. This property is required in these schemas:

1
schemas:
2
simpleObject:
3
type: object
4
required:
5
- objectType
6
properties:
7
objectType:
8
type: string
9
10
complexObject:
11
type: object
12
required:
13
- objectType
14
properties:
15
objectType:
16
type: string
17

The discriminator keyword can be used by various API consumers. One possible example are code generation tools: they can use discriminator to generate program statements that typecast request data to appropriate object type based on the discriminator property value.

Mapping Type Names

It is implied, that the property to which discriminator refers, contains the name of the target schema. In the example above, the objectType property should contain either _simpleObject_, or _complexObject_ string. If the property values do not match the schema names, you can map the values to the names. To do this, use the discriminator/mapping keyword:

1
components:
2
responses:
3
sampleObjectResponse:
4
content:
5
application/json:
6
schema:
7
oneOf:
8
- $ref: '#/components/schemas/Object1'
9
- $ref: '#/components/schemas/Object2'
10
- $ref: 'sysObject.json#/sysObject'
11
discriminator:
12
propertyName: objectType
13
mapping:
14
obj1: '#/components/schemas/Object1'
15
obj2: '#/components/schemas/Object2'
16
system: 'sysObject.json#/sysObject'
17
18
schemas:
19
Object1:
20
type: object
21
required:
22
- objectType
23
properties:
24
objectType:
25
type: string
26
27
Object2:
28
type: object
29
required:
30
- objectType
31
properties:
32
objectType:
33
type: string
34

In this example, the _obj1_ value is mapped to the Object1 model that is defined in the same spec, _obj2_ – to Object2, and the value _system_ matches the sysObject model that is located in an external file. All these objects must have the objectType property with the value _"obj1"_, _"obj2"_ or _"system"_, respectively.

Did not find what you were looking for? Ask the community
Found a mistake? Let us know