FastAPI JSON Output: Quickstart Guide
FastAPI, a modern, fast (high-performance) web framework for building APIs with Python 3.7+, makes working with JSON output incredibly easy. This quickstart guide will walk you through the fundamentals of returning JSON responses in your FastAPI applications.
1. Installation and Basic Setup
First, install FastAPI and an ASGI server like Uvicorn:
bash
pip install fastapi uvicorn
Create a file named main.py
(or any name you prefer) and add the following code:
“`python
from fastapi import FastAPI
app = FastAPI()
@app.get(“/”)
async def root():
return {“message”: “Hello World”}
“`
Run your application using Uvicorn:
bash
uvicorn main:app --reload
This command starts the Uvicorn server. The --reload
flag enables automatic code reloading during development, so you don’t have to restart the server for every change.
Visit http://127.0.0.1:8000/
in your browser. You should see the JSON response:
json
{"message": "Hello World"}
Key Concept: Automatic JSON Serialization
Notice how we simply returned a Python dictionary {"message": "Hello World"}
. FastAPI automatically serializes this dictionary into a JSON response. This is a crucial feature that simplifies your code. You don’t need to manually use json.dumps()
or similar methods.
2. Returning Lists of Data
You can return lists of dictionaries, lists of other data types, or any combination that can be represented as JSON.
“`python
from fastapi import FastAPI
app = FastAPI()
@app.get(“/items/”)
async def read_items():
items = [
{“name”: “Foo”, “price”: 50.2},
{“name”: “Bar”, “price”: 62},
{“name”: “Baz”, “price”: 74.5},
]
return items
“`
Accessing http://127.0.0.1:8000/items/
will show:
json
[
{"name": "Foo", "price": 50.2},
{"name": "Bar", "price": 62},
{"name": "Baz", "price": 74.5}
]
3. Using Pydantic Models for Structured Data
While returning dictionaries is convenient for simple cases, Pydantic models provide significant advantages for more complex data structures:
- Data Validation: Pydantic enforces data types and constraints, ensuring your API returns valid JSON.
- Automatic Documentation: FastAPI uses Pydantic models to automatically generate API documentation (using OpenAPI/Swagger).
- Type Hinting: Pydantic models integrate seamlessly with Python’s type hinting system, improving code readability and maintainability.
Here’s how to use a Pydantic model:
“`python
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
description: str | None = None # Optional string
tax: float | None = None
@app.get(“/items/{item_id}”, response_model=Item) # Specify the response model
async def read_item(item_id: int): #Example of path parameter.
# In a real application, you would fetch the item from a database.
# For this example, we’re just returning a hardcoded item.
if item_id == 1:
return Item(name=”Foo”, price=50.2, description=”A very nice Item”, tax=10.5)
else:
return Item(name=”Bar”, price=32.4) #description and tax are optional, not specifying them sets them to default value None
“`
Key improvements:
from pydantic import BaseModel
: Imports theBaseModel
class from Pydantic.class Item(BaseModel)
: Defines a Pydantic modelItem
with fieldsname
(string),price
(float),description
(optional string), andtax
(optional float). The| None = None
syntax indicates thatdescription
andtax
can be a string/float, orNone
.response_model=Item
: This decorator argument is crucial. It tells FastAPI that the function is expected to return data that conforms to theItem
model. FastAPI will validate the output and raise an error if it doesn’t match. It also uses this information to generate the API documentation.- Path Parameter:
item_id: int
The value of theitem_id
in the URL path is automatically converted to a integer.
Now, if you visit http://127.0.0.1:8000/items/1
, you’ll get:
json
{
"name": "Foo",
"price": 50.2,
"description": "A very nice Item",
"tax": 10.5
}
And http://127.0.0.1:8000/items/2
:
json
{
"name": "Bar",
"price": 32.4,
"description": null,
"tax": null
}
4. Handling Optional Fields and Default Values
As shown in the previous example, you can define optional fields in your Pydantic models using Optional[type]
or the newer type | None
syntax. You can also provide default values:
“`python
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
description: str | None = “No description”
tax: float = 10.5
“`
Here, description
defaults to “No description” if not provided, and tax
defaults to 10.5.
5. Nested Models
You can create complex, nested JSON structures by nesting Pydantic models:
“`python
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Image(BaseModel):
url: str
name: str
class Item(BaseModel):
name: str
price: float
image: Image | None = None # Nested Image model
@app.get(“/items/{item_id}/”, response_model=Item)
async def read_item(item_id: int):
if item_id == 1:
return Item(name=”Foo”, price=50.2, image=Image(url=”http://example.com/foo.jpg”, name=”foo.jpg”))
else:
return Item(name=”Bar”, price=32.5)
“`
Accessing /items/1/
would result in:
json
{
"name": "Foo",
"price": 50.2,
"image": {
"url": "http://example.com/foo.jpg",
"name": "foo.jpg"
}
}
And /items/2/
would return
json
{
"name": "Bar",
"price": 32.5,
"image": null
}
6. Returning Different Response Types (Not Just JSON)
While FastAPI excels at JSON, you can also return other response types using the Response
class or by specifying a different response_class
.
“`python
from fastapi import FastAPI, Response
app = FastAPI()
@app.get(“/plain-text/”)
async def get_plain_text():
return Response(content=”This is plain text”, media_type=”text/plain”)
@app.get(“/html/”)
async def get_html():
return Response(content=”
Hello, world!
“, media_type=”text/html”)
Or, using response_class
from fastapi.responses import PlainTextResponse
@app.get(“/plain-text2/”, response_class=PlainTextResponse)
async def get_plain_text2():
return “This is also plain text”
“`
7. Automatic Documentation (Swagger UI and ReDoc)
FastAPI automatically generates interactive API documentation using OpenAPI (Swagger) and ReDoc. These are accessible at:
- Swagger UI:
http://127.0.0.1:8000/docs
- ReDoc:
http://127.0.0.1:8000/redoc
This documentation is incredibly useful for understanding and testing your API. It reflects the structure of your Pydantic models, including data types, optional fields, and default values. This automatic documentation is one of FastAPI’s killer features.
Conclusion
FastAPI provides a streamlined and powerful way to build APIs with automatic JSON serialization, data validation, and documentation. By combining FastAPI with Pydantic models, you can create robust and well-defined APIs with minimal effort. This quickstart guide covers the fundamentals; explore the official FastAPI documentation for more advanced features and customization options.