From 756902cca1bab981fbec0ea759d93239d9a711f0 Mon Sep 17 00:00:00 2001 From: David Lord Date: Tue, 7 Apr 2020 12:33:00 -0700 Subject: [PATCH] update json docs --- CHANGES.rst | 6 +- docs/api.rst | 42 +++---- src/flask/json/__init__.py | 217 ++++++++++++++++++++----------------- src/flask/json/tag.py | 8 +- 4 files changed, 140 insertions(+), 133 deletions(-) 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 ``