Python Pydantic
· 約3分
Pydantic can extend standard Python classes to provide robust data handling features. BaseModel is the fundamental class in Pydantic. By inheriting from BaseModel, Python classes become Pydantic models, gaining capabilities for:
- Data Validation: Automatically check the types and values of class attributes against your defined type hints. It raises a ValidationError with clear, informative messages if incoming data doesn't confirm.
- Data Coercion: Pydantic can intelligently convert input data to the expected type where appropriate.
- Instantiation: Creates instances of your model by passing keyword arguments or a dictionary to the constructor
Details
Inheriting from BaseModel, Python classes become Pydantic models
You can use Field function, or annotation to add more specific constraints and metadata to your fields.
from typing import Optional
from pydantic import BaseModel, Field, EmailStr
class User(BaseModel):
name: str
age: int
email: str
# Valid data
user = User(name="Alice", age=30, email="[email protected]")
print(user)
# Invalid data will raise a ValidationError
try:
User(name="Bob", age="twenty", email="bob@invalid")
except Exception as e:
print(e)
class Product(BaseModel):
id: int = Field(..., gt=0, description="Unique product identifier")
name: str = Field(..., min_length=2, max_length=100)
price: float = Field(..., gt=0.0)
description: Optional[str] = None # Optional field
seller_email: EmailStr # Pydantic's built-in email validation
product = Product(id=1, name="Laptop", price=1200.50, seller_email="[email protected]")
print(product)
Create Pydantic Model
Directly use Constructor with unpacked dictionary, or model_validate do validate and convert dict to model.
model_validate_json do validate and convert JSON string to a model.
user_data = {
"name": "Alice",
"age": 30,
"email": "[email protected]"
}
user_model = User(**user_data)
user_model = User.model_validate(user_data)
class Movie(BaseModel):
title: str
year: int
director: str
genres: list[str]
# Your JSON string data
json_string = '''
{
"title": "Inception",
"year": 2010,
"director": "Christopher Nolan",
"genres": ["Sci-Fi", "Action", "Thriller"]
}
'''
movie_model = Movie.model_validate_json(json_string)
Validate dictionary and JSON string: model_validate(), model_validate_json()
model_validate: validate a Python dictionary model_validate_json: validate a JSON string
from pydantic import BaseModel
import json
class Item(BaseModel):
name: str
quantity: int
data_dict = {"name": "Apple", "quantity": 5}
item1 = Item.model_validate(data_dict)
print(item1)
json_data = '{"name": "Banana", "quantity": 10}'
item2 = Item.model_validate_json(json_data)
print(item2)
Serialization: model_dump(), model_dump_json().
model_dump: to Python dictionary model_dump_json: to JSON
from pydantic import BaseModel
class City(BaseModel):
name: str
population: int
tokyo = City(name="Tokyo", population=14000000)
print(tokyo.model_dump())
print(tokyo.model_dump_json(indent=2)) # Pretty print JSON
Custom Validators: @field_validator, @model_validator
from datetime import date
from pydantic import BaseModel, ValidationError, field_validator, model_validator
class Event(BaseModel):
name: str
start_date: date
end_date: date
@field_validator('name')
@classmethod
def check_name_is_not_empty(cls, v):
if not v.strip():
raise ValueError('Event name cannot be empty')
return v
@model_validator(mode='after') # 'after' means after field validation
def check_dates_order(self):
if self.start_date > self.end_date:
raise ValueError('Start date must be before end date')
return self
try:
event1 = Event(name="Conference", start_date="2025-07-20", end_date="2025-07-22")
print(event1)
except ValidationError as e:
print(e)
try:
Event(name="Bad Event", start_date="2025-07-25", end_date="2025-07-23")
except ValidationError as e:
print(e)
Nested Models
from pydantic import BaseModel
from typing import List
class Address(BaseModel):
street: str
city: str
zip_code: str
class Customer(BaseModel):
customer_id: int
name: str
shipping_addresses: List[Address]
customer_data = {
"customer_id": 123,
"name": "Jane Doe",
"shipping_addresses": [
{"street": "123 Main St", "city": "Anytown", "zip_code": "12345"},
{"street": "456 Oak Ave", "city": "Otherville", "zip_code": "67890"}
]
}
customer = Customer.model_validate(customer_data)
print(customer)
JSON Schema Generation
from pydantic import BaseModel
class Task(BaseModel):
id: int
title: str
completed: bool = False
print(Task.model_json_schema(indent=2))
References
document on how to use it.