diff --git a/CHANGES.rst b/CHANGES.rst
index a332e406..23bc99ec 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -6,6 +6,9 @@ Version 2.0.0
Unreleased
- Drop support for Python 2 and 3.5.
+- JSON support no longer uses simplejson. To use another JSON module,
+ override ``app.json_encoder`` and ``json_decoder``. :issue:`3555`
+- The ``encoding`` option to JSON functions is deprecated. :pr:`3562`
- Add :meth:`sessions.SessionInterface.get_cookie_name` to allow
setting the session cookie name dynamically. :pr:`3369`
- Add :meth:`Config.from_file` to load config using arbitrary file
@@ -19,9 +22,6 @@ Unreleased
200 OK and an empty file. :issue:`3358`
- When using ad-hoc certificates, check for the cryptography library
instead of PyOpenSSL. :pr:`3492`
-- JSON support no longer uses simplejson if it's installed. To use
- another JSON module, override ``app.json_encoder`` and
- ``json_decoder``. :issue:`3555`
Version 1.1.2
diff --git a/docs/api.rst b/docs/api.rst
index 97c1c7a1..351d9b87 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -279,45 +279,34 @@ Message Flashing
.. autofunction:: get_flashed_messages
+
JSON Support
------------
.. module:: flask.json
-Flask uses the built-in :mod:`json` module for the JSON implementation.
-It will delegate access to the current application's JSON encoders and
-decoders for easier customization.
+Flask uses the built-in :mod:`json` module for handling JSON. It will
+use the current blueprint's or application's JSON encoder and decoder
+for easier customization. By default it handles some extra data types:
-For usage examples, read the :mod:`json` documentation in the standard
-library. The following extensions are by default applied to the stdlib's
-JSON module:
+- :class:`datetime.datetime` and :class:`datetime.date` are serialized
+ to :rfc:`822` strings. This is the same as the HTTP date format.
+- :class:`uuid.UUID` is serialized to a string.
+- :class:`dataclasses.dataclass` is passed to
+ :func:`dataclasses.asdict`.
+- :class:`~markupsafe.Markup` (or any object with a ``__html__``
+ method) will call the ``__html__`` method to get a string.
-1. ``datetime`` objects are serialized as :rfc:`822` strings.
-2. Any object with an ``__html__`` method (like :class:`~flask.Markup`)
- will have that method called and then the return value is serialized
- as string.
-
-The :func:`~htmlsafe_dumps` function of this json module is also available
-as a filter called ``|tojson`` in Jinja2. Note that in versions of Flask prior
-to Flask 0.10, you must disable escaping with ``|safe`` if you intend to use
-``|tojson`` output inside ``script`` tags. In Flask 0.10 and above, this
-happens automatically (but it's harmless to include ``|safe`` anyway).
+:func:`~htmlsafe_dumps` is also available as the ``|tojson`` template
+filter. The filter marks the output with ``|safe`` so it can be used
+inside ``script`` tags.
.. sourcecode:: html+jinja
-.. admonition:: Auto-Sort JSON Keys
-
- The configuration variable :data:`JSON_SORT_KEYS` can be set to
- ``False`` to stop Flask from auto-sorting keys. By default sorting
- is enabled and outside of the app context sorting is turned on.
-
- Notice that disabling key sorting can cause issues when using
- content based HTTP caches and Python's hash randomization feature.
-
.. autofunction:: jsonify
.. autofunction:: dumps
@@ -336,6 +325,7 @@ happens automatically (but it's harmless to include ``|safe`` anyway).
.. automodule:: flask.json.tag
+
Template Rendering
------------------
diff --git a/src/flask/json/__init__.py b/src/flask/json/__init__.py
index 3e9c21a6..6ef22e26 100644
--- a/src/flask/json/__init__.py
+++ b/src/flask/json/__init__.py
@@ -19,33 +19,27 @@ except ImportError:
class JSONEncoder(_json.JSONEncoder):
- """The default Flask JSON encoder. This one extends the default
- encoder by also supporting ``datetime``, ``UUID``, ``dataclasses``,
- and ``Markup`` objects.
+ """The default JSON encoder. Handles extra types compared to the
+ built-in :class:`json.JSONEncoder`.
- ``datetime`` objects are serialized as RFC 822 datetime strings.
- This is the same as the HTTP date format.
+ - :class:`datetime.datetime` and :class:`datetime.date` are
+ serialized to :rfc:`822` strings. This is the same as the HTTP
+ date format.
+ - :class:`uuid.UUID` is serialized to a string.
+ - :class:`dataclasses.dataclass` is passed to
+ :func:`dataclasses.asdict`.
+ - :class:`~markupsafe.Markup` (or any object with a ``__html__``
+ method) will call the ``__html__`` method to get a string.
- In order to support more data types, override the :meth:`default`
- method.
+ Assign a subclass of this to :attr:`flask.Flask.json_encoder` or
+ :attr:`flask.Blueprint.json_encoder` to override the default.
"""
def default(self, o):
- """Implement this method in a subclass such that it returns a
- serializable object for ``o``, or calls the base implementation (to
- raise a :exc:`TypeError`).
-
- For example, to support arbitrary iterators, you could implement
- default like this::
-
- def default(self, o):
- try:
- iterable = iter(o)
- except TypeError:
- pass
- else:
- return list(iterable)
- return JSONEncoder.default(self, o)
+ """Convert ``o`` to a JSON serializable type. See
+ :meth:`json.JSONEncoder.default`. Python does not support
+ overriding how basic types like ``str`` or ``list`` are
+ serialized, they are handled before this method.
"""
if isinstance(o, datetime):
return http_date(o.utctimetuple())
@@ -61,10 +55,13 @@ class JSONEncoder(_json.JSONEncoder):
class JSONDecoder(_json.JSONDecoder):
- """The default JSON decoder. This one does not change the behavior from
- the default decoder. Consult the :mod:`json` documentation
- for more information. This decoder is not only used for the load
- functions of this module but also :attr:`~flask.Request`.
+ """The default JSON decoder.
+
+ This does not change any behavior from the built-in
+ :class:`json.JSONDecoder`.
+
+ Assign a subclass of this to :attr:`flask.Flask.json_decoder` or
+ :attr:`flask.Blueprint.json_decoder` to override the default.
"""
@@ -98,22 +95,20 @@ def _load_arg_defaults(kwargs, app=None):
def dumps(obj, app=None, **kwargs):
- """Serialize ``obj`` to a JSON-formatted string. If there is an
- app context pushed, use the current app's configured encoder
- (:attr:`~flask.Flask.json_encoder`), or fall back to the default
- :class:`JSONEncoder`.
+ """Serialize an object to a string of JSON.
- Takes the same arguments as the built-in :func:`json.dumps`, and
- does some extra configuration based on the application.
+ Takes the same arguments as the built-in :func:`json.dumps`, with
+ some defaults from application configuration.
:param obj: Object to serialize to JSON.
- :param app: App instance to use to configure the JSON encoder.
- Uses ``current_app`` if not given, and falls back to the default
- encoder when not in an app context.
- :param kwargs: Extra arguments passed to :func:`json.dumps`.
+ :param app: Use this app's config instead of the active app context
+ or defaults.
+ :param kwargs: Extra arguments passed to func:`json.dumps`.
+
+ .. versionchanged:: 2.0
+ ``encoding`` is deprecated and will be removed in 2.1.
.. versionchanged:: 1.0.3
-
``app`` can be passed directly, rather than requiring an app
context for configuration.
"""
@@ -135,7 +130,21 @@ def dumps(obj, app=None, **kwargs):
def dump(obj, fp, app=None, **kwargs):
- """Like :func:`dumps` but writes into a file object."""
+ """Serialize an object to JSON written to a file object.
+
+ Takes the same arguments as the built-in :func:`json.dump`, with
+ some defaults from application configuration.
+
+ :param obj: Object to serialize to JSON.
+ :param fp: File object to write JSON to.
+ :param app: Use this app's config instead of the active app context
+ or defaults.
+ :param kwargs: Extra arguments passed to func:`json.dump`.
+
+ .. versionchanged:: 2.0
+ Writing to a binary file, and the ``encoding`` argument, is
+ deprecated and will be removed in 2.1.
+ """
_dump_arg_defaults(kwargs, app=app)
encoding = kwargs.pop("encoding", None)
show_warning = encoding is not None
@@ -158,22 +167,21 @@ def dump(obj, fp, app=None, **kwargs):
def loads(s, app=None, **kwargs):
- """Deserialize an object from a JSON-formatted string ``s``. If
- there is an app context pushed, use the current app's configured
- decoder (:attr:`~flask.Flask.json_decoder`), or fall back to the
- default :class:`JSONDecoder`.
+ """Deserialize an object from a string of JSON.
- Takes the same arguments as the built-in :func:`json.loads`, and
- does some extra configuration based on the application.
+ Takes the same arguments as the built-in :func:`json.loads`, with
+ some defaults from application configuration.
:param s: JSON string to deserialize.
- :param app: App instance to use to configure the JSON decoder.
- Uses ``current_app`` if not given, and falls back to the default
- encoder when not in an app context.
- :param kwargs: Extra arguments passed to :func:`json.dumps`.
+ :param app: Use this app's config instead of the active app context
+ or defaults.
+ :param kwargs: Extra arguments passed to func:`json.dump`.
+
+ .. versionchanged:: 2.0
+ ``encoding`` is deprecated and will be removed in 2.1. The data
+ must be a string or UTF-8 bytes.
.. versionchanged:: 1.0.3
-
``app`` can be passed directly, rather than requiring an app
context for configuration.
"""
@@ -195,7 +203,20 @@ def loads(s, app=None, **kwargs):
def load(fp, app=None, **kwargs):
- """Like :func:`loads` but reads from a file object."""
+ """Deserialize an object from JSON read from a file object.
+
+ Takes the same arguments as the built-in :func:`json.load`, with
+ some defaults from application configuration.
+
+ :param fp: File object to read JSON from.
+ :param app: Use this app's config instead of the active app context
+ or defaults.
+ :param kwargs: Extra arguments passed to func:`json.load`.
+
+ .. versionchanged:: 2.0
+ ``encoding`` is deprecated and will be removed in 2.1. The file
+ must be text mode, or binary mode with UTF-8 bytes.
+ """
_load_arg_defaults(kwargs, app=app)
encoding = kwargs.pop("encoding", None)
@@ -219,84 +240,80 @@ _htmlsafe_map = str.maketrans(
def htmlsafe_dumps(obj, **kwargs):
- """Works exactly like :func:`dumps` but is safe for use in ``