Pydantic in Python
Pydantic is a Python library used for data validation, parsing, and settings management using Python type hints.
It is different from Python’s built-in library Dataclass for similar uses.
It is widely used in frameworks like FastAPI and modern AI systems.
Since Python is dynamically typed, ie
x = 10
x = "abc"will not cause errors during runtime. But as the codebase and complexity grow, we need to have a fixed type for what variables can accept as values to prevent data processing errors and system failures, such as when making a mathematical calculation, which can result in errors if the variables involved have values of invalid data types.
Pydantic enforces types at runtime.
Pydantic helps with data validation, IDE type hints, and JSON serialization.
Install pydantic
pip install pydanticUsing Pydantic we create models that define, validate, and structure data.
To create a model
- Create a model class that inherits from BaseModel class
- Define variables as class variables
- Create instances of the model
from pydantic import BaseModel
class User(BaseModel):
name: str
email: str
age: int
user1 = User(
name = "Alice",
email = "alice@gmail.com",
age = 26
)
# or using Dictionary unpacking
user_data = { 'name':'Bob', 'email':'bob@gmail.com', 'age':26 }
user2 = User(**user_data)
# or validate and parse
user3 = User.model_validate(user_data)If the data passed is valid, the user object is successfully created.
Custom validation
We can use a declarator to define custom validations
# creating a custom validation for age
@validator("age")
def validate_age(cls, value):
if value <= 0:
raise ValueError("age must be greater than 0")
return value
JSON Serialization
Convert Pydantic models to and from JSON.
Get Nimmikrishnab’s stories in your inbox
Join Medium for free to get updates from this writer.
To JSON
user_json1 = user.json()
user_json2 = user.model_dump_json()From JSON to Pydantic model
user = User.parse_raw(json_str)Data Types
- Basic Types: str, int, float, bool
- Container Types: for collection of data, we can define what’s inside
tags: list[str] = ["abc", "edf"]
q: list[int] = [1,2,3]
count: dict[str, int] = {"abc":1, "efg":3}Optional Values
Used when the value might not exist
from typing import Optional
description: Optional[str] = None # if no value then value is None
# or
description: str | None = NoneLiteral Types
When the value must be one of the specific options.
from typing import Literal
progress: Literal["Started","Done"] = "Started"
progress = "Started" # Valid
progress = "Done" # Valid
progress = "OK" # Invalid
Automatic Type Coercion
Pydantic can smartly convert compatible types automatically.
class User(BaseModel):
age: int
user = User(age="25") # no error raisedPydantic will try to convert the entered value to int, and if no error during conversion, then it will accpet the input string “25” and use int 25.
Default Values
class item(BaseModel):
name: str
quantity: int = 10Strict Mode
Disables the automatic type coercion.
from pydantic import BaseModel, ConfigDict
class StrictUser(BaseModel):
model_config = ConfigDict(strict = True)
name: str
age: int
# below will throw error
user = StrictUser(name="abc", age="25")
# valid
user = StrictUser(name="abc", age=25)JSON Schema Generation
Generate JSON schema from models. Useful for API documentation and integration with other tools.
from pydantic import BaseModel, Field
class User(BaseModel):
name: str = Field(min_length = 1, description = "User name")
age: int = Filed(age=0, description= "User age in years")
User.model_json_schema()
# output
{
'properties': {
'name': { 'description':'User name', 'min_length':1, 'type':'string'},
'age': { 'description'= 'User age in years', 'minimum':0, 'type':'integer'}
},
'required':['name','age']
'title':'user'
'type':'Object'
}
Nested Models
Real-world data are often nested
class Person(BaseModel):
name: str
age: int
class Student1(BaseModel):
classes: str
bio: Person
student1 = Student1 (
classes = "physics",
bio = Person(name="Alice", age=25)
)
# list of Person
class Student2(BaseModel):
classes: str
biolist: list[Person]
student_data = { "classes" = "physics",
"biolist" : [{"name":"Alice","age": 25}, {"name":"Bob","age": 25} ]
}
student2 = Student2(**student_data)
Pydantic settings
This is a separate package used for type-safe config from environment variables.
from Pydantic_settings import BaseSettings
class Settings(BaseSettings):
api_key: str
max_connection: int
debug: bool = False
settings = Settings() # redas from environmental variables automaticallyStructure LLM output
Using Pydantic for LLM prompts
response = client.responses.parse(
model = "gpt-4o",
input = "Extract students in physics class"'
text_format = Student
)
result = response.output_parsed
Summary
Pydantic is a Python library that helps you define, validate, and structure data using Python type hints. It ensures that the data your application receives or produces is correct, consistent, and well-structured.







