Pydantic Integration¶
TypedUUID integrates with Pydantic v2 for data validation and serialization.
Installation¶
Basic Usage¶
In Pydantic Models¶
Use TypedUUID directly as a field type:
from pydantic import BaseModel
from typed_uuid import create_typed_uuid_class
UserUUID = create_typed_uuid_class('User', 'user')
class User(BaseModel):
id: UserUUID
name: str
email: str
Creating Model Instances¶
# From TypedUUID instance
user_id = UserUUID()
user = User(id=user_id, name='Alice', email='alice@example.com')
# From string (auto-validated)
user = User(
id='user-550e8400-e29b-41d4-a716-446655440000',
name='Alice',
email='alice@example.com'
)
# From plain UUID string
user = User(
id='550e8400-e29b-41d4-a716-446655440000',
name='Alice',
email='alice@example.com'
)
Validation¶
Pydantic automatically validates TypedUUID fields:
from pydantic import ValidationError
try:
user = User(
id='not-a-valid-uuid',
name='Alice',
email='alice@example.com'
)
except ValidationError as e:
print(e)
# validation error for id
Type mismatches are caught:
OrderUUID = create_typed_uuid_class('Order', 'order')
class Order(BaseModel):
id: OrderUUID
user_id: UserUUID
try:
# Wrong type for user_id
order = Order(
id='order-123e4567-e89b-12d3-a456-426614174000',
user_id='order-123e4567-e89b-12d3-a456-426614174000' # Should be 'user-...'
)
except ValidationError as e:
print(e) # Type mismatch error
Serialization¶
JSON Output¶
TypedUUIDs serialize to strings in JSON:
user = User(id=UserUUID(), name='Alice', email='alice@example.com')
# model_dump() returns dict with string ID
data = user.model_dump()
print(data)
# {'id': 'user-550e8400-...', 'name': 'Alice', 'email': 'alice@example.com'}
# model_dump_json() returns JSON string
json_str = user.model_dump_json()
print(json_str)
# {"id": "user-550e8400-...", "name": "Alice", "email": "alice@example.com"}
Instance Serialization¶
TypedUUID instances have a model_dump() method:
JSON Schema¶
TypedUUID generates proper JSON schemas:
schema = User.model_json_schema()
print(schema['properties']['id'])
# {
# 'type': 'string',
# 'format': 'typed-uuid',
# 'pattern': '^[a-zA-Z0-9]+-[0-9a-f]{8}-...'
# }
This is useful for:
- OpenAPI documentation
- Client SDK generation
- Form validation
Optional Fields¶
Use Optional for nullable fields:
from typing import Optional
class User(BaseModel):
id: UserUUID
manager_id: Optional[UserUUID] = None
name: str
# manager_id can be None or a valid UserUUID
user = User(id=UserUUID(), name='Alice') # manager_id defaults to None
user = User(id=UserUUID(), manager_id=UserUUID(), name='Alice')
Lists and Collections¶
TypedUUIDs work in collections:
from typing import List
class Team(BaseModel):
id: TeamUUID
name: str
member_ids: List[UserUUID]
team = Team(
id=TeamUUID(),
name='Engineering',
member_ids=[UserUUID(), UserUUID(), UserUUID()]
)
Nested Models¶
Use TypedUUIDs in nested models:
class Address(BaseModel):
id: AddressUUID
street: str
city: str
class User(BaseModel):
id: UserUUID
name: str
addresses: List[Address]
user = User(
id=UserUUID(),
name='Alice',
addresses=[
Address(id=AddressUUID(), street='123 Main St', city='Boston'),
Address(id=AddressUUID(), street='456 Oak Ave', city='Cambridge')
]
)
Custom Validation¶
Add additional validation with Pydantic validators:
from pydantic import BaseModel, field_validator
class User(BaseModel):
id: UserUUID
name: str
@field_validator('id', mode='before')
@classmethod
def validate_id(cls, v):
# Custom validation logic
if isinstance(v, str) and v.startswith('admin-'):
raise ValueError('Admin IDs not allowed in User model')
return v
Using validate_json()¶
TypedUUID classes have a validate_json() method:
# Validate a JSON string directly
user_id = UserUUID.validate_json('user-550e8400-e29b-41d4-a716-446655440000')
print(type(user_id)) # UserUUID
Best Practices¶
1. Type All ID Fields¶
# Good: All IDs are typed
class Order(BaseModel):
id: OrderUUID
user_id: UserUUID
product_ids: List[ProductUUID]
# Avoid: Using plain strings for IDs
class Order(BaseModel):
id: str # No type safety
user_id: str
product_ids: List[str]
2. Use Strict Mode When Needed¶
from pydantic import ConfigDict
class StrictUser(BaseModel):
model_config = ConfigDict(strict=True)
id: UserUUID
name: str
# Strict mode requires exact types
3. Document Expected Formats¶
from pydantic import Field
class User(BaseModel):
id: UserUUID = Field(
description="User identifier in format 'user-{uuid}'",
examples=['user-550e8400-e29b-41d4-a716-446655440000']
)
name: str
Compatibility Notes¶
- Requires Pydantic v2.0 or higher
- Pydantic v1 is not supported
- Works with pydantic-settings for configuration management