📖 Scenario: You are building a simple web API using FastAPI. Your API will return information about books. To make it easy for users and other developers to understand and use your API, you want to send responses in a clear, consistent structure.
🎯 Goal: Create a FastAPI app that returns book data in a structured JSON format with keys title, author, and year. This helps clients know exactly what to expect in the response.
📋 What You'll Learn
Create a list of dictionaries with book details
Add a configuration variable for minimum publication year
Filter books published after the minimum year using a list comprehension
Return the filtered books as a JSON response using FastAPI
💡 Why This Matters
🌍 Real World
APIs often serve data to websites and apps. Structured responses ensure all clients get data in a predictable format.
💼 Career
Understanding how to build clear, structured API responses is essential for backend developers and full-stack engineers.
Progress0 / 4 steps
1
Create the initial book data
Create a list called books with these exact dictionaries: {'title': '1984', 'author': 'George Orwell', 'year': 1949}, {'title': 'Brave New World', 'author': 'Aldous Huxley', 'year': 1932}, and {'title': 'Fahrenheit 451', 'author': 'Ray Bradbury', 'year': 1953}.
FastAPI
Hint
Use a list with dictionaries inside. Each dictionary has keys title, author, and year.
2
Add a minimum year filter
Create a variable called min_year and set it to 1940. This will be used to filter books published after this year.
FastAPI
Hint
Just create a variable named min_year and assign the number 1940.
3
Filter books published after the minimum year
Create a new list called filtered_books using a list comprehension that includes only books from books where the year is greater than min_year.
FastAPI
Hint
Use a list comprehension with for book in books and an if condition checking book['year'] > min_year.
4
Return the filtered books as a JSON response
Import FastAPI from fastapi and JSONResponse from fastapi.responses. Create an app instance called app. Define a GET route at /books that returns filtered_books wrapped in JSONResponse.
FastAPI
Hint
Import FastAPI and JSONResponse. Create app = FastAPI(). Use @app.get('/books') decorator. Define async function get_books() that returns JSONResponse(content=filtered_books).
Practice
(1/5)
1. Why is it important to use structured responses in FastAPI APIs?
easy
A. They allow the API to ignore validation rules.
B. They slow down the API response time significantly.
C. They make the API responses clear and predictable for users.
D. They prevent the API from generating documentation.
Solution
Step 1: Understand the role of structured responses
Structured responses define a clear format for API outputs, making them predictable.
Step 2: Recognize benefits in FastAPI
FastAPI uses structured responses to validate data and generate helpful docs automatically.
Final Answer:
They make the API responses clear and predictable for users. -> Option C
Quick Check:
Structured responses = clear, predictable API outputs [OK]
Hint: Structured responses ensure clarity and predictability [OK]
Common Mistakes:
Thinking structured responses slow down APIs
Believing they disable validation
Assuming they block documentation generation
2. Which of the following is the correct way to declare a structured response model in FastAPI using Pydantic?
easy
A. class ResponseModel(BaseModel): name: str; age: int
B. def ResponseModel(name: str, age: int): return dict
C. ResponseModel = {'name': str, 'age': int}
D. class ResponseModel: name = str; age = int
Solution
Step 1: Identify correct Pydantic model syntax
Pydantic models inherit from BaseModel and define fields with type annotations.
Step 2: Compare options
class ResponseModel(BaseModel): name: str; age: int correctly defines a class inheriting BaseModel with typed fields; others do not follow Pydantic syntax.
Final Answer:
class ResponseModel(BaseModel): name: str; age: int -> Option A
Quick Check:
Pydantic model = class with BaseModel and typed fields [OK]
Hint: Use class with BaseModel and type hints for responses [OK]
Common Mistakes:
Defining response as a plain dict
Using functions instead of classes
Missing BaseModel inheritance
3. Given this FastAPI endpoint:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class User(BaseModel):
id: int
name: str
@app.get('/user', response_model=User)
async def get_user():
return {'id': 1, 'name': 'Alice', 'extra': 'ignored'}
What will the API response contain?
medium
A. An error because of the extra field
B. {"id": 1, "name": "Alice"}
C. {"id": 1, "name": "Alice", "extra": "ignored"}
D. {"name": "Alice"}
Solution
Step 1: Understand response_model filtering
FastAPI uses the response_model to filter and validate returned data, ignoring extra fields.
Step 2: Analyze returned dictionary
The returned dict has 'id', 'name', and 'extra'. 'extra' is not in User model, so it is excluded.
Final Answer:
{"id": 1, "name": "Alice"} -> Option B
Quick Check:
response_model filters extra fields = filtered output [OK]
Hint: response_model excludes extra fields automatically [OK]
Common Mistakes:
Expecting extra fields to appear in response
Thinking extra fields cause errors
Ignoring response_model filtering
4. What is wrong with this FastAPI endpoint code?
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
@app.get('/item', response_model=Item)
async def read_item():
return {'name': 'Book'}
medium
A. The endpoint function must not be async.
B. The response_model should not be used with GET requests.
C. The class Item should not inherit from BaseModel.
D. The returned dictionary is missing the 'price' field required by Item.
Solution
Step 1: Check required fields in response_model
The Item model requires 'name' and 'price' fields, both mandatory.
Step 2: Verify returned data matches model
The returned dict only has 'name', missing 'price', causing validation error.
Final Answer:
The returned dictionary is missing the 'price' field required by Item. -> Option D
Quick Check:
Missing required fields in response_model causes errors [OK]
Hint: Returned data must include all required response_model fields [OK]
Common Mistakes:
Ignoring missing required fields
Thinking response_model disallows GET
Believing async is not allowed
5. You want to create a FastAPI endpoint that returns a list of users, each with an id and optional email. Which response model setup correctly ensures structured responses with optional fields?
hard
A. class User(BaseModel): id: int; email: Optional[str]
@app.get('/users', response_model=List[User])
async def get_users(): return [{'id':1}, {'id':2, 'email':'a@b.com'}]
B. class User(BaseModel): id: int; email: str
@app.get('/users', response_model=List[User])
async def get_users(): return [{'id':1}, {'id':2, 'email':'a@b.com'}]
C. class User(BaseModel): id: int
@app.get('/users', response_model=List[User])
async def get_users(): return [{'id':1}, {'id':2, 'email':'a@b.com'}]
D. class User(BaseModel): id: int; email: Optional[str]
@app.get('/users')
async def get_users(): return [{'id':1}, {'id':2, 'email':'a@b.com'}]
Solution
Step 1: Define User model with optional email
Use Optional[str] for email to allow missing values without errors.
Step 2: Use response_model with List[User]
Specify response_model=List[User] to return a list of User objects with validation.
Step 3: Check returned data matches model
Returned list has users with and without email, matching the optional field definition.
Final Answer:
class User(BaseModel): id: int; email: Optional[str]
@app.get('/users', response_model=List[User])
async def get_users(): return [{'id':1}, {'id':2, 'email':'a@b.com'}] -> Option A
Quick Check:
Optional fields + List response_model = correct structured response [OK]
Hint: Use Optional for fields that may be missing in response [OK]
Common Mistakes:
Not marking optional fields as Optional
Missing response_model for list endpoints
Returning extra fields without model support
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.