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.