Examples¶
Complete examples demonstrating pydantic-marshmallow features.
Basic Schema Creation¶
from pydantic import BaseModel, Field, EmailStr
from pydantic_marshmallow import schema_for
class User(BaseModel):
name: str = Field(min_length=1, max_length=100)
email: EmailStr
age: int = Field(ge=0, le=150)
UserSchema = schema_for(User)
schema = UserSchema()
# Load and validate
user = schema.load({
"name": "Alice",
"email": "alice@example.com",
"age": 30
})
print(f"Loaded: {user.name}") # "Loaded: Alice"
Custom Validators¶
from pydantic import BaseModel, Field, field_validator
from pydantic_marshmallow import schema_for
class Product(BaseModel):
name: str = Field(min_length=1)
price: float = Field(gt=0)
sku: str
@field_validator("sku")
@classmethod
def validate_sku(cls, v: str) -> str:
if not v.upper().startswith("SKU-"):
raise ValueError("SKU must start with 'SKU-'")
return v.upper()
schema = schema_for(Product)()
product = schema.load({"name": "Widget", "price": 29.99, "sku": "SKU-12345"})
print(f"SKU: {product.sku}") # "SKU: SKU-12345"
Type Coercion¶
from pydantic import BaseModel
from pydantic_marshmallow import schema_for
class Config(BaseModel):
count: int
enabled: bool
threshold: float
schema = schema_for(Config)()
# Pydantic coerces strings to proper types
config = schema.load({
"count": "42", # string -> int
"enabled": "true", # string -> bool
"threshold": "0.75" # string -> float
})
print(f"Count: {config.count} ({type(config.count).__name__})")
# Count: 42 (int)
Nested Models¶
from pydantic import BaseModel
from pydantic_marshmallow import schema_for
class Address(BaseModel):
street: str
city: str
country: str = "USA"
class Company(BaseModel):
name: str
headquarters: Address
offices: list[Address] = []
schema = schema_for(Company)()
company = schema.load({
"name": "Acme Inc",
"headquarters": {"street": "123 Main St", "city": "New York"},
"offices": [
{"street": "456 Tech Blvd", "city": "San Francisco"},
{"street": "789 Innovation Dr", "city": "Boston"}
]
})
print(f"HQ: {company.headquarters.city}") # "HQ: New York"
print(f"Offices: {[o.city for o in company.offices]}")
# Offices: ['San Francisco', 'Boston']
HybridModel¶
from pydantic import Field
from pydantic_marshmallow import HybridModel
class Order(HybridModel):
order_id: str
customer: str
total: float = Field(ge=0)
items: list[str] = []
# Use as Pydantic model
order = Order(
order_id="ORD-001",
customer="Alice",
total=99.99,
items=["Widget", "Gadget"]
)
# Pydantic methods
print(order.model_dump())
# Marshmallow methods
print(order.ma_dump())
json_str = order.ma_dumps()
# Load via Marshmallow
order2 = Order.ma_load({"order_id": "ORD-002", "customer": "Bob", "total": 149.99})
Batch Loading¶
from pydantic import BaseModel
from pydantic_marshmallow import schema_for
class Task(BaseModel):
title: str
done: bool = False
schema = schema_for(Task)(many=True)
tasks = schema.load([
{"title": "Write code", "done": True},
{"title": "Write tests", "done": True},
{"title": "Deploy", "done": False}
])
for task in tasks:
status = "✓" if task.done else "○"
print(f" {status} {task.title}")
JSON Serialization¶
from datetime import datetime
from pydantic import BaseModel
from pydantic_marshmallow import schema_for
class Event(BaseModel):
name: str
date: datetime
attendees: int = 0
schema = schema_for(Event)()
# Load from JSON string
event = schema.loads('{"name": "Conference", "date": "2024-06-15T09:00:00", "attendees": 500}')
print(f"Event: {event.name} on {event.date}")
# Dump to JSON string
json_str = schema.dumps(event)
print(f"JSON: {json_str}")
Computed Fields¶
from pydantic import BaseModel, computed_field
from pydantic_marshmallow import schema_for
class User(BaseModel):
first: str
last: str
@computed_field # type: ignore[misc]
@property
def full_name(self) -> str:
return f"{self.first} {self.last}"
schema = schema_for(User)()
user = User(first="Alice", last="Smith")
data = schema.dump(user)
print(data)
# {'first': 'Alice', 'last': 'Smith', 'full_name': 'Alice Smith'}