Skip to main content

Built-in Type Support Reference

Flask provides specialized JSON support that extends beyond standard Python types. This implementation is split into two primary systems: the Default JSON Provider for general application use (like API responses) and the Tagged JSON Serializer for internal state management (like session cookies).

Standard Type Support

The DefaultJSONProvider class in src/flask/json/provider.py is the default handler for flask.json.jsonify and app.json.dumps. It extends the standard json library to support several common Python types automatically.

Datetimes and Dates

Objects of type datetime.datetime and datetime.date are serialized to RFC 822 strings using werkzeug.http.http_date. This ensures compatibility with HTTP date headers.

# Example from tests/test_json.py
@app.route("/")
def index():
value = datetime.datetime(1973, 3, 11, 6, 30, 45)
return flask.jsonify(value=value)

# Result: {"value": "Sun, 11 Mar 1973 06:30:45 GMT"}

UUIDs and Decimals

uuid.UUID and decimal.Decimal objects are converted to their string representations. Note that for UUIDs, this includes the standard hyphenated format.

Dataclasses

If the dataclasses module is available, any object decorated with @dataclass is automatically converted to a dictionary using dataclasses.asdict.

# Example from tests/test_basic.py
from dataclasses import make_dataclass

Data = make_dataclass("Data", [("name", str)])
value = app.json.dumps(Data("Flask"))
# Result: '{"name": "Flask"}'

Markup and HTML Objects

Any object that implements a __html__ method (such as markupsafe.Markup) is serialized by calling that method and treating the result as a string.

Provider Configuration

The DefaultJSONProvider exposes several attributes that control how JSON is generated. These are typically configured via the app.json object.

  • ensure_ascii (Default: True): When enabled, non-ASCII characters are escaped (e.g., \u2713). This is controlled by the JSON_AS_ASCII configuration.
  • sort_keys (Default: True): Sorts dictionary keys alphabetically. Note that all keys must be strings for this to work.
  • compact: Controls indentation and whitespace.
    • If None (default), it uses indent=2 when app.debug is True, and compact separators (",", ":") when False.
    • If True, it always uses compact separators.
    • If False, it always uses indent=2.

Lossless Serialization for Sessions

While standard JSON is sufficient for APIs, Flask's session management requires "lossless" serialization to ensure that types like tuple and bytes are preserved exactly when decoded. This is handled by the TaggedJSONSerializer and various JSONTag classes in src/flask/json/tag.py.

When a value is "tagged," it is represented as a dictionary with a single key indicating the type.

Built-in Tags

TypeTag KeyInternal Representation
uuid.UUID" u"Hex string (via TagUUID)
datetime.datetime" d"RFC 822 string (via TagDateTime)
bytes" b"Base64 encoded string (via TagBytes)
markupsafe.Markup" m"HTML string (via TagMarkup)
tuple" t"List of tagged items (via TagTuple)

Example: Tagged UUID vs Standard UUID

In a standard API response (DefaultJSONProvider), a UUID looks like a plain string: "550e8400-e29b-41d4-a716-446655440000"

In a session cookie (TagUUID), it is stored as: {" u": "550e8400e29b41d4a716446655440000"}

This structure allows the TaggedJSONSerializer to recognize the type during loads() and reconstruct the original UUID object instead of leaving it as a string.

Customizing Serialization

Extending the Default Provider

To support additional types in your API responses, you can subclass DefaultJSONProvider and override the default method.

from flask.json.provider import DefaultJSONProvider

class MyProvider(DefaultJSONProvider):
@staticmethod
def default(o):
if isinstance(o, MyCustomType):
return o.to_dict()
return super().default(o)

app.json = MyProvider(app)

Adding Session Tags

For session data, you can create a custom JSONTag and register it with the TaggedJSONSerializer used by your session interface. A tag must implement check, to_json, and to_python.

from flask.json.tag import JSONTag

class TagMyType(JSONTag):
key = " c" # Unique key with a leading space
def check(self, value):
return isinstance(value, MyCustomType)
def to_json(self, value):
return value.id
def to_python(self, value):
return MyCustomType(value)