Modern web applications often use JSON as the primary format for sending and receiving data. Whether you're building REST APIs or single-page apps, your lightweight Python framework should be able to parse JSON from requests and return JSON in responses.
Why JSON Matters
JSON is the de facto standard for client-server communication in modern web development. It's supported by all major front-end frameworks and API consumers.
Supporting JSON enables your framework to:
- Accept structured input from clients
- Return machine-readable responses
- Handle API endpoints cleanly
Reading JSON from Requests
Most clients sending JSON set the Content-Type
header to application/json
. Your framework needs to:
- Check that header
- Decode the request body
- Parse the JSON into a Python dictionary
Here’s a basic example:
import json
def parse_json_body(request):
content_type = request["headers"].get("Content-Type", "")
if "application/json" in content_type:
try:
body = request.get("body", b"")
return json.loads(body.decode("utf-8"))
except (ValueError, UnicodeDecodeError):
return None
return None
Writing JSON Responses
To return JSON, serialize your Python object and set the correct headers:
def json_response(data, status=200):
return {
"status": status,
"headers": {
"Content-Type": "application/json"
},
"body": json.dumps(data).encode("utf-8")
}
Example Endpoint
A simple handler that accepts and returns JSON:
def echo_handler(request):
data = parse_json_body(request)
if data is None:
return json_response({"error": "Invalid JSON"}, status=400)
return json_response({"you_sent": data})
Common Pitfalls
- Missing Content-Type: Some clients forget to set headers; decide if you want to accept raw bodies anyway
- Non-UTF8 encoding: JSON is expected to be UTF-8; reject otherwise
-
Invalid syntax: Always catch exceptions from
json.loads()
- Large payloads: Consider adding a max size check
JSON Middleware (Optional)
You can wrap JSON parsing into a middleware that adds .json
to the request object:
def json_parser_middleware(request, next_handler):
request["json"] = parse_json_body(request)
return next_handler(request)
Then in your handlers, access request["json"]
directly.
Returning Errors in JSON
For consistency, even error messages should be structured:
def not_found():
return json_response({"error": "Not found"}, status=404)
Testing JSON Endpoints
Use curl
for quick local testing:
curl -X POST http://localhost:8000/api/echo \
-H "Content-Type: application/json" \
-d '{"name": "Alice"}'
Or use browser tools like Postman or HTTPie.
Wrap-Up
Adding JSON support makes your lightweight Python framework more powerful and compatible with modern frontend and mobile apps. It’s easy to implement and opens the door to building full-featured APIs.
Want to dive deeper? Check out my 20-page PDF guide: Building a Lightweight Python Web Framework from Scratch
Top comments (0)