Pydantic is a popular library which we can use for defining our custom objects and making it so much easy to use for day to day coding.
Here is one of the example that i link can really boost productivity - this is how we can assign data into our objects.
from pydantic import BaseModel, EmailStr, Field
class UserRegistration(BaseModel):
username: str = Field(min_length=3, max_length=20)
age: int = Field(ge=18) # Must be 18 or older
# Incoming untrusted JSON data
raw_input = {"username": "alice_dev", "email": "alice@example.com", "age": "25"}
# Pydantic validates and coerces data types automatically
user = UserRegistration(**raw_input)
print(user.age) # Output: 25 (converted from string to int)
Application settings
To work with an app config that automatically read from DATABASE_URL and REDIS_URL environment variables. Pre-req, you need to install uv add pydantic_settings
from pydantic import PostgresDsn, RedisDsn
from pydantic_settings import BaseSettings, SettingsConfigDict
class AppConfig(BaseSettings):
# Automatically reads DATABASE_URL and REDIS_URL from environment or .env
database_url: PostgresDsn
redis_url: RedisDsn
debug_mode: bool = False
max_connections: int = 100
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8")
# Loads settings at app startup; throws immediate errors if critical ENV vars are missing/invalid
config = AppConfig()
LLM
This is useful when passing in a predefined schema into OpenAPI based LLM model.
from pydantic import BaseModel, Field
class SentimentAnalysis(BaseModel):
sentiment: str = Field(description="Must be 'positive', 'negative', or 'neutral'")
confidence_score: float = Field(ge=0.0, le=1.0)
key_topics: list[str] = Field(description="Extracted key topics mentioned in the text")
# Example schema passed to OpenAI's structured output API:
schema = SentimentAnalysis.model_json_schema()
Working with complex json object
Raw API responses often contain deeply nested JSON, bad casing (e.g., camelCase), or missing fields. Pydantic can map camelCase to Pythonic snake_case and transform nested payload structures during ingestion.
from pydantic import BaseModel, Field, AliasChoices
class OrderItem(BaseModel):
product_id: str = Field(validation_alias=AliasChoices("product_id", "productId"))
unit_price: float = Field(validation_alias=AliasChoices("unit_price", "unitPrice"))
quantity: int
class OrderPayload(BaseModel):
order_id: str = Field(validation_alias=AliasChoices("order_id", "orderId"))
items: list[OrderItem]
# Raw camelCase JSON payload from an external API vendor
raw_vendor_json = {
"orderId": "ORD-9921",
"items": [
{"productId": "PROD-A", "unitPrice": 19.99, "quantity": 2}
]
}
# Automatically maps camelCase to snake_case attributes
order = OrderPayload.model_validate(raw_vendor_json)
print(order.items[0].unit_price) # Output: 19.99
We can also used it for schema validations as shown in the diagram below :-
from datetime import date
from pydantic import BaseModel, field_validator, model_validator
class EventBooking(BaseModel):
event_name: str
start_date: date
end_date: date
discount_code: str | None = None
# Field Validator: Normalize discount codes to uppercase
@field_validator("discount_code")
@classmethod
def uppercase_discount(cls, value: str | None) -> str | None:
return value.upper() if value else value
# Model Validator: Validate relationships across multiple fields
@model_validator(mode="after")
def check_dates(self) -> "EventBooking":
if self.end_date < self.start_date:
raise ValueError("end_date cannot be earlier than start_date")
return self
Comments