Basic Nested Models
from pydantic import BaseModel
from typing import Optional
from justapi import JustAPIApp
class Address(BaseModel):
street: str
city: str
state: str
zip_code: str
class User(BaseModel):
name: str
email: str
address: Address
secondary_address: Optional[Address] = None
app = JustAPIApp()
@app.post("/users")
def create_user(user: User):
return user.model_dump()
The client sends:
{
"name": "Alice",
"email": "alice@example.com",
"address": {
"street": "123 Main St",
"city": "Springfield",
"state": "IL",
"zip_code": "62701"
}
}
Lists of Nested Models
class Tag(BaseModel):
name: str
color: str = "gray"
class Item(BaseModel):
name: str
tags: list[Tag] = []
@app.post("/items")
def create_item(item: Item):
return item.model_dump()
{
"name": "Widget",
"tags": [
{"name": "hardware", "color": "blue"},
{"name": "sale", "color": "red"}
]
}
Set Types
Use set to deduplicate values:
class Item(BaseModel):
name: str
tags: set[str] = set()
@app.post("/items")
def create_item(item: Item):
return item.model_dump()
{
"name": "Widget",
"tags": ["hardware", "sale", "hardware"]
}
The response deduplicates:
{
"name": "Widget",
"tags": ["hardware", "sale"]
}
Bodies of Pure Lists
The entire request body can be a list:
class Image(BaseModel):
url: str
caption: str = ""
@app.post("/images")
def create_images(images: list[Image]):
return {"count": len(images), "images": images}
[
{"url": "https://example.com/img1.jpg", "caption": "Photo 1"},
{"url": "https://example.com/img2.jpg"}
]
Bodies of Arbitrary Dicts
Use dict for dynamic keys:
@app.post("/metrics")
def record_metrics(metrics: dict[str, float]):
return {"metrics": metrics}
{
"cpu": 75.5,
"memory": 62.3,
"disk": 45.1
}
Typed keys:
@app.post("/config")
def update_config(config: dict[str, str]):
return {"config": config}
Special Types
Pydantic includes types for common formats:
from pydantic import BaseModel, HttpUrl, EmailStr
class Website(BaseModel):
url: HttpUrl
contact_email: EmailStr
@app.post("/websites")
def create_website(website: Website):
return {"url": str(website.url), "email": str(website.contact_email)}
| Type | Validates |
|---|---|
HttpUrl |
Valid HTTP/HTTPS URL |
EmailStr |
Valid email address |
AnyUrl |
Any valid URL |
IPvAnyAddress |
Valid IP address |
AnyHttpUrl |
HTTP or HTTPS URL |
Deeply Nested Structures
class Comment(BaseModel):
author: str
text: str
replies: list["Comment"] = []
class Post(BaseModel):
title: str
content: str
comments: list[Comment] = []
@app.post("/posts")
def create_post(post: Post):
return post.model_dump()
Validation at Every Level
JustAPI validates the entire nested structure. Invalid data at any level returns a clear error:
{
"detail": [
{
"type": "string_type",
"loc": ["body", "address", "zip_code"],
"msg": "Input should be a valid string",
"input": 12345
}
]
}
See Also
- Request Body — basic Pydantic usage
- Body — Fields — field-level validation
- Extra Models — multiple related models