I am trying to use Literal
to create a discriminated union with Pydantic.
There are events about a Job resource, and I want to distinguish them by event_name
. For JobPublishedEvents
I want to ensure, that some extra_field
is present.
class GenericJobEvent(BaseModel):
event_name: str
id: int
class JobPublishedEvent(GenericJobEvent):
event_name: Literal['job.published']
extra_field: str
class Wrapper(BaseModel):
wrapped: Union[JobPublishedEvent, GenericJobEvent]
print(type(Wrapper(wrapped={'event_name': 'some.event', 'id': 1}).wrapped)) # GenericJobEvent
print(type(Wrapper(wrapped={'event_name': 'job.published', 'id': 1, 'extra_field': 'extra'}).wrapped)) # JobPublishedEvent
print(type(Wrapper(wrapped={'event_name': 'job.published', 'id': 1}).wrapped)) # GenericJobEvent
The first 2 cases behave as expected, for the third I would like a validation error since the literal matches, but the schema is not fulfilled. I get why the fallback to the GenericJobEvent is valid, though.
Does anybody have an idea on how to achieve this?