Complete worked example
python
from typing import Annotated
from pydantic import BaseModel, ConfigDict, Field, ValidationError
Tag = Annotated[str, Field(min_length=2, max_length=12)]
class Filters(BaseModel):
model_config = ConfigDict(extra="forbid")
page_size: Annotated[int, Field(ge=1, le=20)] = 10
tags: list[Tag] = Field(default_factory=list, max_length=3)
def inspect_example(payload):
try:
return {"value": Filters.model_validate(payload).model_dump()}
except ValidationError as error:
return {"error": sorted({e["type"] for e in error.errors()})}- Reasoning
- The Tag alias combines str with Field bounds. The Filters model then uses list[Tag] and a separate maximum list length. A default_factory provides an empty list when tags are absent, while extra="forbid" makes unexpected top-level request keys visible as errors. The example returns a normal dumped mapping for accepted input or stable validation error types for rejected input. Follow an empty tag through item validation, then follow four ordinary tags through collection validation. Both are invalid, but they fail different contracts. The supplied cases make that difference observable.