Skip to main content

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 (like markupsafe.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: When True (default), dictionary keys are sorted alphabetically. Note that all keys must be strings for sorting to work.
  • ensure_ascii: When True (default), non-ASCII characters are escaped (e.g., \u2713). Set to False for smaller responses when using UTF-8.
  • compact: Controls indentation. If None (default), output is indented in debug mode and compact in production. Set to True or False to 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.