oneOf, anyOf, allOf, not
OpenAPI 3.0 provides several keywords which you can use to combine schemas. You can use these keywords to create a complex schema, or validate a value against multiple criteria.
oneOf
– validates the value against exactly one of the subschemasallOf
– validates the value against all the subschemasanyOf
– validates the value against any (one or more) of the subschemas
Besides these, there is a not
keyword which you can use to make sure the value is not valid against the specified schema.
oneOf
Use the oneOf
keyword to ensure the given data is valid against one of the specified schemas.
1paths:2 /pets:3 patch:4 requestBody:5 content:6 application/json:7 schema:8 oneOf:9 - $ref: "#/components/schemas/Cat"10 - $ref: "#/components/schemas/Dog"11 responses:12 "200":13 description: Updated14
15components:16 schemas:17 Dog:18 type: object19 properties:20 bark:21 type: boolean22 breed:23 type: string24 enum: [Dingo, Husky, Retriever, Shepherd]25 Cat:26 type: object27 properties:28 hunts:29 type: boolean30 age:31 type: integer
The example above shows how to validate the request body in the “update” operation (PATCH). You can use it to validate the request body contains all the necessary information about the object to be updated, depending on the object type. Note the inline or referenced schema must be a schema object, not a standard JSON Schema. Now, to validation. The following JSON object is valid against one of the schemas, so the request body is correct:
1{ "bark": true, "breed": "Dingo" }
The following JSON object is not valid against both schemas, so the request body is incorrect:
1{ "bark": true, "hunts": true }
The following JSON object is valid against both schemas, so the request body is incorrect – it should be valid against only one of the schemas, since we are using the oneOf
keyword.
1{ "bark": true, "hunts": true, "breed": "Husky", "age": 3 }
allOf
OpenAPI lets you combine and extend model definitions using the allOf
keyword. allOf
takes an array of object definitions that are used for independent validation but together compose a single object. Still, it does not imply a hierarchy between the models. For that purpose, you should include the discriminator
. To be valid against allOf
, the data provided by the client must be valid against all of the given subschemas. In the following example, allOf
acts as a tool for combining schemas used in specific cases with the general one. For more clearness, oneOf
is also used with a discriminator
.
1paths:2 /pets:3 patch:4 requestBody:5 content:6 application/json:7 schema:8 oneOf:9 - $ref: "#/components/schemas/Cat"10 - $ref: "#/components/schemas/Dog"11 discriminator:12 propertyName: pet_type13 responses:14 "200":15 description: Updated16
17components:18 schemas:19 Pet:20 type: object21 required:22 - pet_type23 properties:24 pet_type:25 type: string26 discriminator:27 propertyName: pet_type28
29 Dog: # "Dog" is a value for the pet_type property (the discriminator value)30 allOf: # Combines the main `Pet` schema with `Dog`-specific properties31 - $ref: "#/components/schemas/Pet"32 - type: object33 # all other properties specific to a `Dog`34 properties:35 bark:36 type: boolean37 breed:38 type: string39 enum: [Dingo, Husky, Retriever, Shepherd]40
41 Cat: # "Cat" is a value for the pet_type property (the discriminator value)42 allOf: # Combines the main `Pet` schema with `Cat`-specific properties43 - $ref: "#/components/schemas/Pet"44 - type: object45 # all other properties specific to a `Cat`46 properties:47 hunts:48 type: boolean49 age:50 type: integer
As you can see, this example validates the request body content to make sure it includes all the information needed to update a pet item with the PUT operation. It requires user to specify which type of the item should be updated, and validates against the specified schema according to their choice. Note the inline or referenced schema must be a schema object, not a standard JSON schema. For that example, all of the following request bodies are valid:
1{2 "pet_type": "Cat",3 "age": 34}5
6{7 "pet_type": "Dog",8 "bark": true9}10
11{12 "pet_type": "Dog",13 "bark": false,14 "breed": "Dingo"15}
The following request bodies are not valid:
1{2 "age": 3 # Does not include the pet_type property3}4
5
6
7{8 "pet_type": "Cat",9 "bark": true # The `Cat` schema does not have the `bark` property10}
anyOf
Use the anyOf
keyword to validate the data against any amount of the given subschemas. That is, the data may be valid against one or more subschemas at the same time.
1paths:2 /pets:3 patch:4 requestBody:5 content:6 application/json:7 schema:8 anyOf:9 - $ref: "#/components/schemas/PetByAge"10 - $ref: "#/components/schemas/PetByType"11 responses:12 "200":13 description: Updated14
15components:16 schemas:17 PetByAge:18 type: object19 properties:20 age:21 type: integer22 nickname:23 type: string24 required:25 - age26
27 PetByType:28 type: object29 properties:30 pet_type:31 type: string32 enum: [Cat, Dog]33 hunts:34 type: boolean35 required:36 - pet_type
Note the inline or referenced schema must be a schema object, not a standard JSON schema. With this example, the following JSON request bodies are valid:
1{2 "age": 13}4
5{6 "pet_type": "Cat",7 "hunts": true8}9
10{11 "nickname": "Fido",12 "pet_type": "Dog",13 "age": 414}
The following example is not valid, because it does not contain any of the required properties for both of the schemas:
1{ "nickname": "Mr. Paws", "hunts": false }
Difference Between anyOf and oneOf
oneOf
matches exactly one subschema, and anyOf
can match one or more subschemas. To better understand the difference, use the example above but replace anyOf
with oneOf
. When using oneOf
, the following request body is not valid because it matches both schemas and not just one:
1{ "nickname": "Fido", "pet_type": "Dog", "age": 4 }
not
The not
keyword does not exactly combine schemas, but as all of the keywords mentioned above it helps you to modify your schemas and make them more specific.
1paths:2 /pets:3 patch:4 requestBody:5 content:6 application/json:7 schema:8 $ref: "#/components/schemas/PetByType"9 responses:10 "200":11 description: Updated12
13components:14 schemas:15 PetByType:16 type: object17 properties:18 pet_type:19 not:20 type: integer21 required:22 - pet_type
In this example, user should specify the pet_type
value of any type except integer (that is, it should be an array, boolean, number, object, or string). The following request body is valid:
1{ "pet_type": "Cat" }
And the following is not valid:
1{ "pet_type": 11 }
Did not find what you were looking for? Ask the community Found a mistake? Let us know