Body — Nested Models
Basic Nested Models
Section titled “Basic Nested Models”from pydantic import BaseModelfrom typing import Optionalfrom 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
Section titled “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
Section titled “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
Section titled “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
Section titled “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
Section titled “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
Section titled “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
Section titled “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
Section titled “See Also”- Request Body — basic Pydantic usage
- Body — Fields — field-level validation
- Extra Models — multiple related models