pallets/flask · error · TypeError

Object of type is not JSON serializable

Error message

Object of type {type(o).__name__} is not JSON serializable

What it means

_default(o) is Flask's JSON encoder fallback for objects the standard json module cannot serialize. It handles date/datetime, Decimal, UUID, dataclasses, and objects with __html__. If an object matches none of these, it raises TypeError naming the object's type. This surfaces during jsonify/dumps when your data contains an unsupported type like a SQLAlchemy model instance, a set, bytes, or a custom class.

Solutions

  1. Convert the object to a serializable form before jsonify: model.to_dict(), list(my_set), my_bytes.decode(), enum.value.
  2. Subclass DefaultJSONProvider and override _default or dumps to handle your custom types, then set app.json.
  3. Use marshmallow/pydantic to serialize complex objects to dicts.

Example fix

# before
@app.route('/u')
def user():
    return jsonify(db.session.get(User, 1))  # User not serializable

# after
@app.route('/u')
def user():
    u = db.session.get(User, 1)
    return jsonify({'id': u.id, 'name': u.name})
Defensive patterns

Strategy: type-guard

Validate before calling

import dataclasses, datetime, decimal, uuid, json

def is_json_serializable(o) -> bool:
    return isinstance(o, (str, int, float, bool, type(None), list, tuple, dict,
                          datetime.date, datetime.datetime, decimal.Decimal, uuid.UUID)) \
        or (dataclasses.is_dataclass(o)) or hasattr(o, '__html__')

# validate before jsonify
def assert_serializable(obj):
    json.dumps(obj, default=lambda o: (_ for _ in ()).throw(
        TypeError(f'{type(o).__name__} not serializable')) if not is_json_serializable(o) else o))

Type guard

import datetime, decimal, uuid, dataclasses

def is_default_serializable(o) -> bool:
    return isinstance(o, (str, int, float, bool, type(None), list, tuple, dict,
                          datetime.date, decimal.Decimal, uuid.UUID)) \
        or dataclasses.is_dataclass(o) or hasattr(o, '__html__')

Try / catch

from flask.json.provider import DefaultJSONProvider
import json

class SafeJSONProvider(DefaultJSONProvider):
    def dumps(self, obj, **kw):
        try:
            return super().dumps(obj, **kw)
        except TypeError:
            return super().dumps(str(obj), **kw)
app.json = SafeJSONProvider(app)

Prevention

When it happens

Trigger: Returning jsonify(obj) where obj (or a nested value) is a type Flask does not serialize by default: a set, bytes, a custom class without __html__, a SQLAlchemy InstrumentedList, an Enum, or a Pandas DataFrame. _default is called by json.dumps for each unhandled object.

Common situations: Passing ORM objects to jsonify instead of dicts. Forgetting to convert a set to a list. Returning bytes or a custom value object. Using Enum members in API responses without a default encoder.

Related errors


AI-assisted analysis of pallets/flask@3596b1ab61 (2026-08-11). Data as JSON: /api/errors/d69686dda339bade. Report an issue: GitHub.

Appendix: source

Thrown at src/flask/json/provider.py:121

        """
        obj = self._prepare_response_obj(args, kwargs)
        return self._app.response_class(self.dumps(obj), mimetype="application/json")


def _default(o: t.Any) -> t.Any:
    if isinstance(o, date):
        return http_date(o)

    if isinstance(o, (decimal.Decimal, uuid.UUID)):
        return str(o)

    if dataclasses and dataclasses.is_dataclass(o):
        return dataclasses.asdict(o)  # type: ignore[arg-type]

    if hasattr(o, "__html__"):
        return str(o.__html__())

    raise TypeError(f"Object of type {type(o).__name__} is not JSON serializable")


class DefaultJSONProvider(JSONProvider):
    """Provide JSON operations using Python's built-in :mod:`json`
    library. Serializes the following additional data types:

    -   :class:`datetime.datetime` and :class:`datetime.date` are
        serialized to :rfc:`822` strings. This is the same as the HTTP
        date format.
    -   :class:`uuid.UUID` is serialized to a string.
    -   :class:`dataclasses.dataclass` is passed to
        :func:`dataclasses.asdict`.
    -   :class:`~markupsafe.Markup` (or any object with a ``__html__``
        method) will call the ``__html__`` method to get a string.
    """

    default: t.Callable[[t.Any], t.Any] = staticmethod(_default)
    """Apply this function to any object that :meth:`json.dumps` does

View on GitHub (pinned to 3596b1ab61)