Standard JSON Support
The DefaultJSONProvider is the default engine for JSON operations in Flask, accessible via app.json and used by flask.jsonify. It extends Python's built-in json library to automatically handle common types like datetimes, UUIDs, and dataclasses.
Automatically Serializing Complex Types
You can return complex Python objects directly from your routes using flask.jsonify. The DefaultJSONProvider handles the conversion to JSON-compatible formats.
from datetime import datetime
from uuid import uuid4
from dataclasses import dataclass
from flask import Flask, jsonify
@dataclass
class User:
id: int
name: str
app = Flask(__name__)
@app.route("/data")
def get_data():
return jsonify(
timestamp=datetime(2023, 10, 27, 12, 0, 0),
request_id=uuid4(),
user=User(id=1, name="Flask User")
)
The DefaultJSONProvider applies the following conversions:
- Datetimes/Dates: Converted to RFC 822 strings (HTTP date format) using
werkzeug.http.http_date. - UUIDs: Converted to their string representation.
- Dataclasses: Converted to dictionaries using
dataclasses.asdict. - Decimals: Converted to their string representation.
- Markup: Objects with an
__html__method (likemarkupsafe.Markup) are converted to strings by calling that method.
Configuring JSON Behavior
You can customize the serialization behavior by modifying attributes on app.json. These settings affect all JSON responses generated by the application.
app = Flask(__name__)
# Disable key sorting (enabled by default)
app.json.sort_keys = False
# Disable ASCII-only escaping to allow UTF-8 characters
app.json.ensure_ascii = False
# Force compact output even in debug mode
app.json.compact = True
Configuration Options
sort_keys: WhenTrue(default), dictionary keys are sorted alphabetically. Note that all keys must be strings for sorting to work.ensure_ascii: WhenTrue(default), non-ASCII characters are escaped (e.g.,\u2713). Set toFalsefor smaller responses when using UTF-8.compact: Controls indentation. IfNone(default), output is indented in debug mode and compact in production. Set toTrueorFalseto override this behavior.mimetype: The content type for responses, defaults to"application/json".
Customizing Serialization Logic
If you need to support additional types, you can override the default method of the provider or create a custom provider subclass.
Overriding the Default Handler
The simplest way to add support for a custom type is to provide a new function to app.json.default.
from flask.json.provider import DefaultJSONProvider
class CustomObject:
def __init__(self, value):
self.value = value
def custom_default(obj):
if isinstance(obj, CustomObject):
return {"_type": "CustomObject", "val": obj.value}
# Fall back to the standard provider logic
return DefaultJSONProvider.default(obj)
app = Flask(__name__)
app.json.default = custom_default
Creating a Custom Provider Subclass
For more complex changes, such as modifying how JSON is loaded, subclass DefaultJSONProvider and assign it to app.json.
from flask.json.provider import DefaultJSONProvider
class CustomProvider(DefaultJSONProvider):
def dumps(self, obj, **kwargs):
# Add custom logic before or after serialization
return super().dumps(obj, **kwargs)
def loads(self, s, **kwargs):
# Add custom logic for deserialization
return super().loads(s, **kwargs)
app = Flask(__name__)
app.json = CustomProvider(app)
Troubleshooting
Mixed Arguments in jsonify
The response() method (called by jsonify) accepts either positional arguments or keyword arguments, but not both.
# This works (positional)
jsonify([1, 2, 3])
# This works (keyword)
jsonify(a=1, b=2)
# This raises a TypeError
jsonify([1, 2], c=3)
Date Format
By default, DefaultJSONProvider serializes datetimes to RFC 822 format (e.g., Fri, 27 Oct 2023 12:00:00 GMT). If your client expects ISO 8601 (e.g., 2023-10-27T12:00:00), you must override the default handler as shown in the customization section.
Key Sorting Requirements
If app.json.sort_keys is True, all keys in a dictionary must be strings. If you attempt to serialize a dictionary with mixed key types (e.g., {1: "a", "b": "c"}), the underlying json.dumps will raise a TypeError.