OAS 3 This page applies to OpenAPI 3 – the latest version of the OpenAPI Specification.

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 subschemas
  • allOf – validates the value against all the subschemas
  • anyOf – 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.
paths:
  /pets:
    patch:
      requestBody:
        content:
          application/json:
            schema:
              oneOf:
                - $ref: '#/components/schemas/Cat'
                - $ref: '#/components/schemas/Dog'
      responses:
        '200':
          description: Updated

components:
  schemas:
    Dog:
      type: object
      properties:
        bark:
          type: boolean
        breed:
          type: string
          enum: [Dingo, Husky, Retriever, Shepherd]
    Cat:
      type: object
      properties:
        hunts:
          type: boolean
        age:
          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 response body is correct:
{
  "bark": true,
  "breed": "Dingo" 
}
The following JSON object is not valid against both schemas, so the response body is incorrect:
{
  "bark": true,
  "hunts": true
}
The following JSON object is valid against both schemas, so the response body is incorrect – it should be valid against only one of the schemas, since we are using the oneOf keyword.
{
  "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.
paths:
  /pets:
    patch:
      requestBody:
        content:
          application/json:
            schema:
              oneOf:
                - $ref: '#/components/schemas/Cat'
                - $ref: '#/components/schemas/Dog'
              discriminator:
                propertyName: pet_type
      responses:
        '200':
          description: Updated

components:
  schemas:
    Pet:
      type: object
      required:
        - pet_type
      properties:
        pet_type:
          type: string
      discriminator:
        propertyName: pet_type

    Dog:     # "Dog" is a value for the pet_type property (the discriminator value)
      allOf: # Combines the main `Pet` schema with `Dog`-specific properties 
        - $ref: '#/components/schemas/Pet'
        - type: object
          # all other properties specific to a `Dog`
          properties:
            bark:
              type: boolean
            breed:
              type: string
              enum: [Dingo, Husky, Retriever, Shepherd]

    Cat:     # "Cat" is a value for the pet_type property (the discriminator value)
      allOf: # Combines the main `Pet` schema with `Cat`-specific properties 
        - $ref: '#/components/schemas/Pet'
        - type: object
          # all other properties specific to a `Cat`
          properties:
            hunts:
              type: boolean
            age:
              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:
{
  "pet_type": "Cat",
  "age": 3
}
{
  "pet_type": "Dog",
  "bark": true
}
{
  "pet_type": "Dog",
  "bark": false,
  "breed": "Dingo"
}
The following request bodies are not valid:
{
  "age": 3        # Does not include the pet_type property
}
 
{
  "pet_type": "Cat", 
  "bark": true    # The `Cat` schema does not have the `bark` property 
}
 

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.
paths:
  /pets:
    patch:
      requestBody:
        content:
          application/json:
            schema:
              anyOf:
                - $ref: '#/components/schemas/PetByAge'
                - $ref: '#/components/schemas/PetByType'
      responses:
        '200':
          description: Updated

components:
  schemas:
    PetByAge:
      type: object
      properties: 
        age: 
          type: integer
        nickname: 
          type: string
      required:
        - age
          
    PetByType:
      type: object
      properties:
        pet_type:
          type: string
          enum: [Cat, Dog]
        hunts:
          type: boolean
      required: 
        - 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:
{
  "age": 1
}
{
  "pet_type": "Cat",
  "hunts": true
}
{
  "nickname": "Fido",
  "pet_type": "Dog",
  "age": 4
}
The following example is not valid, because it does not contain any of the required properties for both of the schemas:
{
  "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:
{
  "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.
paths:
  /pets:
    patch:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PetByType'
      responses:
        '200':
          description: Updated

components:
  schemas:          
    PetByType:
      type: object
      properties:
        pet_type:
          not:
            type: integer
      required:
        - 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:
{
  "pet_type": "Cat"
}
And the following is not valid:
{
  "pet_type": 11
}