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

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.

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: Ada

Inside 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.

TaskCode
Serialize to responsejsonify(data)
Parse incoming JSONrequest.get_json()
Date to stringvalue.isoformat()
Object to dictobj.to_dict()

🏆 Mini Challenge: Serialize a Product List

Build a route that serializes a list of Product objects into JSON.

# 🏆 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

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().