pydantic
$
npx mdskill add TerminalSkills/skills/pydanticValidate and serialize data using Python type hints with Pydantic
- Solve data validation and serialization tasks for APIs, config, and models
- Uses Python type hints and integrates with FastAPI, LangChain, and ORM systems
- Applies validation rules, type coercion, and serialization based on model definitions
- Returns structured data outputs in JSON or Python objects for downstream use
SKILL.md
.github/skills/pydanticView on GitHub ↗
---
name: pydantic
description: >-
Validate and serialize data with Pydantic. Use when a user asks to validate
API inputs, parse JSON/env config, define data models in Python, serialize
objects, or implement data validation with type hints.
license: Apache-2.0
compatibility: 'Python 3.10+'
metadata:
author: terminal-skills
version: 1.0.0
category: development
tags:
- pydantic
- validation
- python
- data
- serialization
---
# Pydantic
## Overview
Pydantic is a data validation library that uses Python type hints. Define a model class, and Pydantic validates inputs, coerces types, and serializes outputs automatically. Used by FastAPI, LangChain, and most modern Python frameworks.
## Instructions
### Step 1: Basic Models
```python
# schemas.py — Data models with validation
from pydantic import BaseModel, Field, EmailStr, field_validator
from datetime import datetime
class UserCreate(BaseModel):
name: str = Field(min_length=2, max_length=100)
email: EmailStr
age: int = Field(ge=13, le=120)
role: str = Field(default="member", pattern="^(admin|member|viewer)$")
class UserResponse(BaseModel):
id: str
name: str
email: str
role: str
created_at: datetime
model_config = {"from_attributes": True} # works with ORM objects
# Usage
user = UserCreate(name="Alice", email="alice@example.com", age=28)
print(user.model_dump()) # {"name": "Alice", "email": "alice@example.com", ...}
print(user.model_dump_json()) # JSON string
# Validation error
try:
UserCreate(name="A", email="not-an-email", age=5)
except ValidationError as e:
print(e.errors())
# [{"type": "string_too_short", "loc": ["name"], ...}, ...]
```
### Step 2: Custom Validators
```python
from pydantic import BaseModel, field_validator, model_validator
class ProjectCreate(BaseModel):
name: str
slug: str
start_date: datetime
end_date: datetime | None = None
@field_validator("slug")
@classmethod
def validate_slug(cls, v: str) -> str:
if not v.replace("-", "").isalnum():
raise ValueError("Slug must contain only letters, numbers, and hyphens")
return v.lower()
@model_validator(mode="after")
def validate_dates(self):
if self.end_date and self.end_date <= self.start_date:
raise ValueError("End date must be after start date")
return self
```
### Step 3: Settings from Environment
```python
# config.py — App configuration from env vars
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
database_url: str
redis_url: str = "redis://localhost:6379"
secret_key: str
debug: bool = False
allowed_origins: list[str] = ["http://localhost:3000"]
max_upload_mb: int = 10
model_config = {
"env_file": ".env",
"env_file_encoding": "utf-8",
}
settings = Settings() # auto-reads from .env and environment variables
```
### Step 4: Discriminated Unions
```python
# events.py — Polymorphic event types
from pydantic import BaseModel
from typing import Literal
class TaskCreated(BaseModel):
type: Literal["task.created"] = "task.created"
task_id: str
project_id: str
title: str
class TaskCompleted(BaseModel):
type: Literal["task.completed"] = "task.completed"
task_id: str
completed_by: str
duration_hours: float
class CommentAdded(BaseModel):
type: Literal["comment.added"] = "comment.added"
comment_id: str
task_id: str
body: str
# Discriminated union — Pydantic picks the right type based on "type" field
WebhookEvent = TaskCreated | TaskCompleted | CommentAdded
# Parse any event
event = WebhookEvent.model_validate({"type": "task.completed", "task_id": "123", ...})
# Returns TaskCompleted instance
```
## Guidelines
- Pydantic v2 is 5-50x faster than v1 — rewritten in Rust (pydantic-core).
- Use `Field(...)` for constraints: `min_length`, `max_length`, `ge`, `le`, `pattern`.
- `from_attributes = True` enables direct serialization of ORM objects (SQLAlchemy, Django).
- Use `pydantic-settings` for type-safe configuration from environment variables.
- Discriminated unions handle polymorphic data — Pydantic picks the right model based on a field value.
More from TerminalSkills/skills