Validate JSON payloads with Pydantic

Python
from pydantic import BaseModel, Field, ValidationError, field_validator


class Signup(BaseModel):
    email: str
    age: int = Field(ge=13, le=120)
    nickname: str = Field(min_length=2, max_length=30)

    @field_validator("email")
    @classmethod
    def email_must_look_valid(cls, value: str) -> str:
        if "@" not in value or value.startswith("@"):
            raise ValueError("invalid email address")
        return value.lower()


def parse_signup(payload: dict) -> tuple[Signup | None, list[str]]:
    """Return the model plus readable field errors for an API response."""
    try:
        return Signup(**payload), []
    except ValidationError as exc:
        issues = [f"{'.'.join(map(str, err['loc']))}: {err['msg']}" for err in exc.errors()]
        return None, issues


if __name__ == "__main__":
    print(parse_signup({"email": "[email protected]", "age": 36, "nickname": "ada"}))
    print(parse_signup({"email": "nope", "age": 9, "nickname": "a"}))