FastAPI JSON Output: Quickstart Guide

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 the BaseModel class from Pydantic.
  • class Item(BaseModel): Defines a Pydantic model Item with fields name (string), price (float), description (optional string), and tax(optional float). The | None = None syntax indicates that description and tax can be a string/float, or None.
  • response_model=Item: This decorator argument is crucial. It tells FastAPI that the function is expected to return data that conforms to the Item 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 the item_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.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top