Skip to content

Body — 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"
}
}
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"}
]
}

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"]
}

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"}
]

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}

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
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()

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
}
]
}