Pydantic: Validation

calico·2025년 12월 8일

Python

목록 보기
4/10

https://mobicon.tistory.com/627

How Pydantic Validation Works


  • Pydantic is a Python library that uses type hints to validate, coerce, and structure input data.

  • When you define a BaseModel, Pydantic treats the type annotations as a schema and automatically enforces that schema whenever you create a model instance.


Step 1: You Define a Model Using Type Hints


Example:

from datetime import datetime
from pydantic import BaseModel, PositiveInt

class User(BaseModel):
    id: int
    name: str = 'John Doe'
    signup_ts: datetime | None
    tastes: dict[str, PositiveInt]

Each annotation describes:

  • the field name (id, name, signup_ts, …)

  • the expected type

  • optional default values

These types are the validation rules.



Step 2: You Provide Data → Pydantic Validates It


When you create a model:

user = User(**external_data)

Pydantic:

  • Reads your input

  • Validates each field

  • Converts (coerces) values when allowed

  • Raises detailed errors when validation fails

Example coercions Pydantic can perform:

Field typeInputWhat Pydantic does
int"123"converts to 123
datetime"2020-01-02T03:04:05Z"parses into a datetime object
tuple[int, int]["10", "20"]converts to (10, 20)
PositiveInt"7"parses and validates positivity



Step 3: Pydantic Returns a Validated Model


Pydantic stores the validated, converted values inside the model:

print(user.model_dump())

Example output:

{
    'id': 123,
    'name': 'John Doe',
    'signup_ts': datetime.datetime(2019, 6, 1, 12, 22),
    'tastes': {'wine': 9, 'cheese': 7, 'cabbage': 1},
}

Notice:

  • String → datetime conversion succeeded
  • Byte string keys (b'cheese') became "cheese"
  • "1" became integer 1 for PositiveInt



Step 4: If Something Is Wrong → ValidationError


If any field fails validation, Pydantic raises a ValidationError:

try:
    User(id="not an int", tastes={})
except ValidationError as e:
    print(e.errors())

Sample error description:

[
    {
        'type': 'int_parsing',
        'msg': 'Input should be a valid integer',
        'loc': ('id',),
        'input': 'not an int',
    },
    {
        'type': 'missing',
        'msg': 'Field required',
        'loc': ('signup_ts',),
    }
]

Key features of Pydantic’s errors:

  • exact error type (int_parsing, missing, …)
  • field location (('id',))
  • error message
  • invalid input
  • URL to detailed docs

This makes debugging very easy.



Optional: Strict Mode vs Lax Mode


By default, Pydantic is lax: it tries to coerce values.

But you can enable strict mode to prevent coercion:

from pydantic import BaseModel, StrictInt

class Model(BaseModel):
    x: StrictInt

Now:

Model(x="1")  # ❌ fails, no conversion allowed



Custom Validators (Pydantic v2)


You can add your own validation rules:

from pydantic import BaseModel, field_validator

class User(BaseModel):
    age: int

    @field_validator("age")
    def check_age(cls, v):
        if v < 0:
            raise ValueError("Age must be positive")
        return v



Pydantic validation works by:
1. Reading type hints from your model
2. Using these as a schema
3. Coercing types when allowed
4. Validating values deeply
5. Producing powerful error messages on failure
6. Returning structured Python objects on success


It gives you:

  • familiar Python syntax
  • automatic type enforcement
  • extremely fast validation (written in Rust)
  • great error reporting
  • deep integration with other tools (e.g., FastAPI, Logfire)



profile
All views expressed here are solely my own and do not represent those of any affiliated organization.

0개의 댓글