justapi — /docs

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

JustAPI v2.0.9 — Open Source MIT License · Built with WebTUI · GitHub

NORMAL master justapi/docs
utf-8 Top 1:1