Modeling Polymorphic Responses in OpenAPI 3.1 with Discriminators
An API that returns different shapes for the same endpoint forces clients to guess. A discriminator in OpenAPI 3.1 makes polymorphic responses explicit by naming a property that selects the concrete subtype in a oneOf composition.
11 Feb 2026, 09:18 UTC

The problem is clients guessing the shape
An endpoint returns a Pet, but sometimes it is a Dog and sometimes a Cat. Without a clear selector, clients inspect the payload for hints, rely on out-of-band documentation, or try both shapes. That is brittle and breaks when a new subtype appears.
The useful takeaway is to make the choice explicit in the schema. A discriminator declares a property whose value selects the concrete subtype inside a oneOf composition. The API documents which values are valid and what follows, so deserialization becomes deterministic.
What a discriminator actually does
In OpenAPI 3.1, which aligns with JSON Schema 2020-12, a discriminator is metadata on a parent schema. It names a property that must exist in every subtype and must be required. The value of that property maps to one member of a oneOf list.
oneOf means exactly one schema must match. allOf is used to reuse common fields without duplication. Together they let you define a base shape and extend it per subtype while keeping the spec DRY with $ref components.
OpenAPI 3.0 also supports discriminators, but the mapping rules and JSON Schema alignment differ. Tooling that targets 3.0 may ignore some 3.1 nuances, so version assumptions matter for code generation and validation.
Worked example: /pets with Dog and Cat
Parent schema Pet declares petType as the discriminator and requires it. The oneOf lists Dog and Cat.
components:
schemas:
Pet:
type: object
required: [petType]
discriminator:
propertyName: petType
oneOf:
- $ref: '#/components/schemas/Dog'
- $ref: '#/components/schemas/Cat'
Animal:
type: object
properties:
name:
type: string
age:
type: integer
Dog:
allOf:
- $ref: '#/components/schemas/Animal'
- type: object
required: [petType, breed]
properties:
petType:
type: string
enum: [dog]
breed:
type: string
Cat:
allOf:
- $ref: '#/components/schemas/Animal'
- type: object
required: [petType, indoor]
properties:
petType:
type: string
enum: [cat]
indoor:
type: boolean
The endpoint can reference Pet for both request and response bodies. A payload with petType: dog must validate against Dog, and petType: cat must validate against Cat. The discriminator property is present in all subtypes and is required, which makes the contract explicit.
Tooling support and practical trade-offs
Code generators commonly use the discriminator to emit type-safe union types or classes and to enable type narrowing on the discriminator property. That improves client ergonomics.
Support varies across tools and is version-sensitive. Older OpenAPI 3.0 tooling may ignore JSON Schema features introduced in 3.1. Check the generator changelog for explicit discriminator support before relying on it.
Limitations are real. Overusing polymorphism increases client complexity and can hinder caching and schema evolution. Prefer flat schemas when subtypes differ only slightly. The discriminator property must be immutable and unique per subtype; changing its name or allowed values is a breaking change.
Verification steps you can apply without assuming test results:
- Validate the document with an OpenAPI 3.1 validator and confirm the discriminator property is required in each subtype and declared on the parent.
- Run a code generator for your target language and inspect the generated union types to ensure the discriminator is used for narrowing.
- Test request and response examples for each subtype to confirm the discriminator value correctly selects the schema during validation.
Use discriminators when polymorphism is a first-class domain concept and the selector is stable. Document the allowed values, keep the discriminator required, and avoid adding subtypes that only change a few optional fields. That keeps the API self-documenting and easier to integrate.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.