Skip to content

[Feature Request] Provide a discriminated union type (OpenAPI 3) #619

@sm-Fifteen

Description

@sm-Fifteen

Feature Request

Pydantic currently has a decent support for union types through the typing.Union type from PEP484, but it does not currently cover all the cases covered by the JSONSchema and OpenAPI specifications, most likely because the two specifications diverge on those points.

OpenAPI supports something similar to tagged unions where a certain field is designated to serve as a "discriminator", which is then matched against literal values to determine which of multiple schemas to use for payload validation. In order to allow Pydantic to support those, I suppose there would have to be a specific type similar to typing.Union in order to specify what discriminator field to use and how to match it. Such a type would then be rendered into a schema object (oneOf) with an OpenAPI discriminator object built into it, as well as correctly validate incoming JSON into the correct type based on the value or the discriminator field. This change would only impact OpenAPI, as JSON schema (draft 7 onwards) uses conditional types instead, which would probably need to be the topic of a different feature request, as both methods appear mutually incompatible.

Implementation ideas

I'd imagine the final result to be something like this.

MyUnion = Union[Foo, Bar]
MyTaggedUnion = TaggedUnion(Union[Foo, Bar], discriminator='type', mapping={'foo': Foo, 'bar': Bar}))

Python doesn't have a feature like TypeScript to let you statically ensure that discriminator exists as a field for all variants of that union, though that shouldn't be a problem since this is going to be raised during validation regardless.

discriminator and mapping could also simply be added to Schema, though I'm not sure about whether it's a good idea to add OpenAPI-specific extensions there.

PEP 593 would also have been a nice alternative, since it would hypothetically allow tagged unions to be implemented as a regular union with annotations specific to Pydantic for that purpose, however it is only still a draft and most likely won't make it until Python 3.9 (if at all).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions