JSON & Serialization
Reviewed & published by Brayan K
Serialization is the process of converting an in-memory Python object — like a dictionary or a database model — into JSON text that can travel across the web, and deserialization is turning that text back into an object you can use.
Part of the free Flask course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.
In this lesson you'll serialize Python data with jsonify(), parse incoming JSON with request.get_json(), and handle tricky types like dates that aren't JSON-ready by default.
What You'll Learn in This Lesson
- What JSON is and how it maps to Python types
- What serialization and deserialization mean
- How jsonify() builds a JSON response
- How request.get_json() parses incoming data
- How to write a to_dict() serializer for objects
- How to handle non-serializable types like dates
1 JSON and Python Types
JSON is a text format for structured data. It looks almost exactly like a Python dictionary, which is why Flask can translate between the two so easily. A small JSON object might look like this:
{
"id": 1,
"title": "Learn Flask",
"tags": ["python", "web"],
"done": false
}Each JSON type lines up with a Python type. Understanding the mapping makes serialization predictable — when you pass a Python dict to jsonify(), you can picture the JSON it will produce.
- Python dict becomes a JSON object
- Python list becomes a JSON array
- Python str becomes a JSON string
- Python True / None become JSON true / null
2 Serializing Out and Parsing In
jsonify() is the serializer: it takes a Python dictionary or list and returns a complete JSON response. request.get_json() is the deserializer: it reads the JSON a client sent and gives you back a Python dictionary.
The endpoint below echoes data back to the caller. It parses the incoming JSON, adds a field, and serializes the result. Run it with flask run and POST some JSON to try it.
# app.py — serialize out, deserialize in
from flask import Flask, jsonify, request
app = Flask(__name__)
@app.route("/echo", methods=["POST"])
def echo():
incoming = request.get_json() # deserialize: JSON -> dict
if incoming is None:
return jsonify({"error": "Send JSON"}), 400
incoming["received"] = True # modify the Python dict
return jsonify(incoming), 200 # serialize: dict -> JSON
# Demonstrate serialization with the standard library.
import json
person = {"name": "Ada", "skills": ["python", "math"], "active": True}
as_text = json.dumps(person) # serialize to a JSON string
print("Serialized:", as_text)
back = json.loads(as_text) # deserialize back to a dict
print("Deserialized name:", back["name"])
# Run live with flask run, then POST JSON to /echo
# ✅ Expected output:
# Serialized: {"name": "Ada", "skills": ["python", "math"], "active": true}
# Deserialized name: AdaInside a Flask route always prefer jsonify() over json.dumps() — it sets the application/json header so clients parse the response correctly.
3 Serializing Objects & Awkward Types
A custom class or a database model can't be serialized directly. The standard fix is a to_dict() method that returns only JSON-friendly fields. For a datetime, call .isoformat() to turn it into a string first.
The example below defines a User class with a join date and a to_dict() serializer, then returns it as JSON.
# app.py — serialize a custom object safely
from flask import Flask, jsonify
from datetime import datetime
app = Flask(__name__)
class User:
def __init__(self, user_id, name, joined):
self.id = user_id
self.name = name
self.joined = joined # a datetime — not JSON-ready!
def to_dict(self):
# Convert every field to a JSON-friendly type.
return {
"id": self.id,
"name": self.name,
"joined": self.joined.isoformat(), # datetime -> string
}
@app.route("/user")
def get_user():
user = User(1, "Ada", datetime(2024, 1, 15))
return jsonify(user.to_dict()) # serialize the dict, not the object
# Demonstrate the conversion without a server.
user = User(1, "Ada", datetime(2024, 1, 15))
print("Serializable form:", user.to_dict())
# Passing the raw object would raise:
# TypeError: Object of type User is not JSON serializable
# Run live with flask run, then visit /user
# ✅ Expected output:
# Serializable form: {'id': 1, 'name': 'Ada', 'joined': '2024-01-15T00:00:00'}🎯 Your Turn: Fill in the Blanks
Complete the route so it parses JSON, builds a serializable dict, and returns it. Replace each ___.
# 🎯 YOUR TURN: finish the serialization
from flask import Flask, jsonify, request
from datetime import datetime
app = Flask(__name__)
@app.route("/profile", methods=["POST"])
def profile():
data = request.___() # parse the incoming JSON
if data is None:
return jsonify({"error": "Send JSON"}), 400
result = {
"name": data.get("name"),
"created": datetime(2024, 5, 1).___(), # datetime -> string
}
return ___(result), 200 # serialize the dict to JSON
print("Route ready for POST /profile")Common Errors & Quick Reference
❌ TypeError: Object of type datetime is not JSON serializable
You passed a value JSON can't represent. Convert it first — use .isoformat() for dates, list(...) for sets, or a to_dict() method for custom objects.
❌ Client can't read my response as JSON
You probably returned json.dumps(data), which sends plain text. Use jsonify(data) instead so Flask sets the application/json header.
| Task | Code |
|---|---|
| Serialize to response | jsonify(data) |
| Parse incoming JSON | request.get_json() |
| Date to string | value.isoformat() |
| Object to dict | obj.to_dict() |
🏆 Mini Challenge: Serialize a Product List
Build a route that serializes a list of Product objects into JSON.
- Give the Product class a to_dict() method
- Build a list of products in the route
- Return them as JSON with jsonify()
# 🏆 Mini Challenge: serialize a list of objects
from flask import Flask, jsonify
app = Flask(__name__)
class Product:
def __init__(self, pid, name, price):
self.id = pid
self.name = name
self.price = price
def to_dict(self):
return {"id": self.id, "name": self.name, "price": self.price}
@app.route("/products")
def list_products():
products = [
Product(1, "Keyboard", 49.99),
Product(2, "Mouse", 19.99),
]
# Serialize each object, then jsonify the list.
return jsonify([p.to_dict() for p in products])
# Demonstrate without a server.
items = [Product(1, "Keyboard", 49.99), Product(2, "Mouse", 19.99)]
print([p.to_dict() for p in items])
# Run live with flask run, then visit /products❓ Frequently Asked Questions
Lesson complete — you mastered JSON in Flask!
You can serialize data with jsonify(), parse it with request.get_json(), write a to_dict() serializer, and convert awkward types like dates so they're JSON-ready.
Practice quiz
What is serialization?
- Encrypting a password
- Compressing a file
- Opening a database connection
- Converting an in-memory object into JSON text
Answer: Converting an in-memory object into JSON text. Serialization turns a Python object into JSON text that can travel over the web.
Which Flask function builds a complete JSON response?
- jsonify()
- render_template()
- make_json()
- to_json()
Answer: jsonify(). jsonify() serializes a dict or list into a JSON response with the right header.
How do you parse JSON a client sent in a request?
- request.form.json
- request.get_json()
- request.read_json
- request.parse()
Answer: request.get_json(). request.get_json() deserializes the incoming JSON body into a Python dict.
A Python dict serializes to which JSON type?
- A JSON string
- A JSON number
- A JSON object
- A JSON array
Answer: A JSON object. A Python dict becomes a JSON object; a list becomes a JSON array.
Why prefer jsonify() over json.dumps() inside a route?
- It is faster to type
- It validates the schema
- It sorts the keys
- It sets the application/json header so clients parse it correctly
Answer: It sets the application/json header so clients parse it correctly. jsonify() sets the Content-Type to application/json; json.dumps() returns plain text.
How do you make a custom object JSON-serializable?
- Give it a to_dict() method returning JSON-friendly fields
- Call str() on it
- Pass it straight to jsonify
- Pickle it first
Answer: Give it a to_dict() method returning JSON-friendly fields. A to_dict() method returns only JSON-friendly fields, which you then jsonify.
How do you make a datetime JSON-ready?
- Wrap it in a list
- Call .isoformat() to turn it into a string
- Call jsonify on it directly
- Convert it to bytes
Answer: Call .isoformat() to turn it into a string. datetime isn't JSON-native; .isoformat() converts it to a string.
Python True and None serialize to which JSON values?
- 1 and 0
- "True" and "None"
- true and null
- yes and no
Answer: true and null. True maps to JSON true and None maps to JSON null.
What error do you get passing a raw datetime to jsonify?
- KeyError
- SyntaxError
- ImportError
- TypeError: Object of type datetime is not JSON serializable
Answer: TypeError: Object of type datetime is not JSON serializable. JSON can't represent datetime directly, raising that TypeError.
A bonus of writing to_dict() is that you can also...
- Speed up the database
- Omit private fields like a password hash from the response
- Skip routing
- Disable CORS
Answer: Omit private fields like a password hash from the response. to_dict() lets you leave sensitive fields out of the API response.
Continue this course
- Previous: Building a REST API
- Next: Authentication & Login — Register, log in, and protect routes with Flask-Login and hashed passwords
- Quick reference: Flask cheat sheet › Request & Response
Frequently asked questions
What is JSON?
JSON (JavaScript Object Notation) is a lightweight, text-based data format. It represents data as key-value objects and arrays, and almost every programming language can read and write it, which makes it the standard format for web APIs.
What does serialization mean?
Serialization is the process of converting an in-memory object — like a Python dictionary or a database model — into a transmittable format such as a JSON string. Deserialization is the reverse: turning that text back into an object.
How does jsonify() differ from json.dumps()?
json.dumps() returns a plain string, while Flask's jsonify() builds a full HTTP response with the correct application/json Content-Type header and proper formatting. Inside a Flask route you almost always want jsonify().
Why do I get 'Object is not JSON serializable'?
Some Python types — like datetime objects or custom classes — have no automatic JSON form. You must convert them yourself first, for example turning a datetime into a string with .isoformat(), before passing the data to jsonify().