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 theJSON_AS_ASCIIconfiguration.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 usesindent=2whenapp.debugisTrue, and compact separators(",", ":")whenFalse. - If
True, it always uses compact separators. - If
False, it always usesindent=2.
- If
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
| Type | Tag Key | Internal 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)