Pydantic Field Validator Coercion
Normalize messy form input with Pydantic field validators, trimming strings, coercing digit strings, and rejecting malformed values early.
Code
from typing import Annotated
from pydantic import BaseModel, Field, field_validator, model_validator
class SignupForm(BaseModel):
email: Annotated[str, Field(min_length=5, max_length=120)]
age: Annotated[int, Field(ge=18, le=120)]
zipcode: str
password: str
password_confirm: str
@field_validator('email', mode='before')
@classmethod
def normalize_email(cls, raw: object) -> object:
if isinstance(raw, str):
candidate = raw.strip().lower()
if candidate.startswith('mailto:'):
candidate = candidate.removeprefix('mailto:')
return candidate
return raw
@field_validator('zipcode', mode='before')
@classmethod
def digits_only(cls, raw: object) -> object:
if isinstance(raw, str) and raw.isdigit() and len(raw) == 5:
return raw
raise ValueError('zipcode must be exactly 5 digits')
@model_validator(mode='after')
def passwords_match(self) -> 'SignupForm':
if self.password != self.password_confirm:
raise ValueError('passwords do not match')
return self
form = SignupForm(
email=' MAILTO:[email protected] ',
age='30',
zipcode='02138',
password='hunter2xx',
password_confirm='hunter2xx',
)
print('normalized email:', form.email, 'age type:', type(form.age).__name__)Report a problem with this exampleOpens a pre-filled issue on GitHub.