bazarr/libs/flask/json/__init__.py

343 lines
11 KiB
Python
Raw Normal View History

2022-11-07 18:06:49 +00:00
from __future__ import annotations
import json as _json
import typing as t
2019-11-28 11:40:45 +00:00
from jinja2.utils import htmlsafe_json_dumps as _jinja_htmlsafe_dumps
2019-11-28 11:40:45 +00:00
from ..globals import current_app
2022-11-07 18:06:49 +00:00
from .provider import _default
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
if t.TYPE_CHECKING: # pragma: no cover
from ..app import Flask
from ..wrappers import Response
2019-11-28 11:40:45 +00:00
class JSONEncoder(_json.JSONEncoder):
"""The default JSON encoder. Handles extra types compared to the
built-in :class:`json.JSONEncoder`.
- :class:`datetime.datetime` and :class:`datetime.date` are
serialized to :rfc:`822` strings. This is the same as the HTTP
date format.
2022-11-07 18:06:49 +00:00
- :class:`decimal.Decimal` is serialized to a string.
- :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.
Assign a subclass of this to :attr:`flask.Flask.json_encoder` or
:attr:`flask.Blueprint.json_encoder` to override the default.
2022-11-07 18:06:49 +00:00
.. deprecated:: 2.2
Will be removed in Flask 2.3. Use ``app.json`` instead.
2019-11-28 11:40:45 +00:00
"""
2022-11-07 18:06:49 +00:00
def __init__(self, **kwargs) -> None:
import warnings
warnings.warn(
"'JSONEncoder' is deprecated and will be removed in"
" Flask 2.3. Use 'Flask.json' to provide an alternate"
" JSON implementation instead.",
DeprecationWarning,
stacklevel=3,
)
super().__init__(**kwargs)
def default(self, o: t.Any) -> t.Any:
"""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.
2019-11-28 11:40:45 +00:00
"""
2022-11-07 18:06:49 +00:00
return _default(o)
2019-11-28 11:40:45 +00:00
class JSONDecoder(_json.JSONDecoder):
"""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.
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
.. deprecated:: 2.2
Will be removed in Flask 2.3. Use ``app.json`` instead.
"""
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
def __init__(self, **kwargs) -> None:
import warnings
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
warnings.warn(
"'JSONDecoder' is deprecated and will be removed in"
" Flask 2.3. Use 'Flask.json' to provide an alternate"
" JSON implementation instead.",
DeprecationWarning,
stacklevel=3,
)
super().__init__(**kwargs)
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
def dumps(obj: t.Any, *, app: Flask | None = None, **kwargs: t.Any) -> str:
"""Serialize data as JSON.
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
If :data:`~flask.current_app` is available, it will use its
:meth:`app.json.dumps() <flask.json.provider.JSONProvider.dumps>`
method, otherwise it will use :func:`json.dumps`.
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
:param obj: The data to serialize.
:param kwargs: Arguments passed to the ``dumps`` implementation.
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
.. versionchanged:: 2.2
Calls ``current_app.json.dumps``, allowing an app to override
the behavior.
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
.. versionchanged:: 2.2
The ``app`` parameter will be removed in Flask 2.3.
.. versionchanged:: 2.0.2
:class:`decimal.Decimal` is supported by converting to a string.
.. versionchanged:: 2.0
2022-11-07 18:06:49 +00:00
``encoding`` will be removed in Flask 2.1.
.. versionchanged:: 1.0.3
``app`` can be passed directly, rather than requiring an app
context for configuration.
2019-11-28 11:40:45 +00:00
"""
2022-11-07 18:06:49 +00:00
if app is not None:
import warnings
2019-11-28 11:40:45 +00:00
warnings.warn(
2022-11-07 18:06:49 +00:00
"The 'app' parameter is deprecated and will be removed in"
" Flask 2.3. Call 'app.json.dumps' directly instead.",
DeprecationWarning,
stacklevel=2,
)
2022-11-07 18:06:49 +00:00
else:
app = current_app
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
if app:
return app.json.dumps(obj, **kwargs)
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
kwargs.setdefault("default", _default)
return _json.dumps(obj, **kwargs)
2019-11-28 11:40:45 +00:00
def dump(
2022-11-07 18:06:49 +00:00
obj: t.Any, fp: t.IO[str], *, app: Flask | None = None, **kwargs: t.Any
) -> None:
2022-11-07 18:06:49 +00:00
"""Serialize data as JSON and write to a file.
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
If :data:`~flask.current_app` is available, it will use its
:meth:`app.json.dump() <flask.json.provider.JSONProvider.dump>`
method, otherwise it will use :func:`json.dump`.
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
:param obj: The data to serialize.
:param fp: A file opened for writing text. Should use the UTF-8
encoding to be valid JSON.
:param kwargs: Arguments passed to the ``dump`` implementation.
.. versionchanged:: 2.2
Calls ``current_app.json.dump``, allowing an app to override
the behavior.
.. versionchanged:: 2.2
The ``app`` parameter will be removed in Flask 2.3.
.. versionchanged:: 2.0
2022-11-07 18:06:49 +00:00
Writing to a binary file, and the ``encoding`` argument, will be
removed in Flask 2.1.
"""
2022-11-07 18:06:49 +00:00
if app is not None:
import warnings
warnings.warn(
2022-11-07 18:06:49 +00:00
"The 'app' parameter is deprecated and will be removed in"
" Flask 2.3. Call 'app.json.dump' directly instead.",
DeprecationWarning,
stacklevel=2,
)
2022-11-07 18:06:49 +00:00
else:
app = current_app
if app:
app.json.dump(obj, fp, **kwargs)
else:
kwargs.setdefault("default", _default)
_json.dump(obj, fp, **kwargs)
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
def loads(s: str | bytes, *, app: Flask | None = None, **kwargs: t.Any) -> t.Any:
"""Deserialize data as JSON.
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
If :data:`~flask.current_app` is available, it will use its
:meth:`app.json.loads() <flask.json.provider.JSONProvider.loads>`
method, otherwise it will use :func:`json.loads`.
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
:param s: Text or UTF-8 bytes.
:param kwargs: Arguments passed to the ``loads`` implementation.
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
.. versionchanged:: 2.2
Calls ``current_app.json.loads``, allowing an app to override
the behavior.
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
.. versionchanged:: 2.2
The ``app`` parameter will be removed in Flask 2.3.
2019-11-28 11:40:45 +00:00
.. versionchanged:: 2.0
2022-11-07 18:06:49 +00:00
``encoding`` will be removed in Flask 2.1. The data must be a
string or UTF-8 bytes.
2019-11-28 11:40:45 +00:00
.. versionchanged:: 1.0.3
``app`` can be passed directly, rather than requiring an app
context for configuration.
"""
2022-11-07 18:06:49 +00:00
if app is not None:
import warnings
2019-11-28 11:40:45 +00:00
warnings.warn(
2022-11-07 18:06:49 +00:00
"The 'app' parameter is deprecated and will be removed in"
" Flask 2.3. Call 'app.json.loads' directly instead.",
DeprecationWarning,
stacklevel=2,
)
2022-11-07 18:06:49 +00:00
else:
app = current_app
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
if app:
return app.json.loads(s, **kwargs)
2019-11-28 11:40:45 +00:00
return _json.loads(s, **kwargs)
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
def load(fp: t.IO[t.AnyStr], *, app: Flask | None = None, **kwargs: t.Any) -> t.Any:
"""Deserialize data as JSON read from a file.
If :data:`~flask.current_app` is available, it will use its
:meth:`app.json.load() <flask.json.provider.JSONProvider.load>`
method, otherwise it will use :func:`json.load`.
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
:param fp: A file opened for reading text or UTF-8 bytes.
:param kwargs: Arguments passed to the ``load`` implementation.
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
.. versionchanged:: 2.2
Calls ``current_app.json.load``, allowing an app to override
the behavior.
.. versionchanged:: 2.2
The ``app`` parameter will be removed in Flask 2.3.
.. versionchanged:: 2.0
2022-11-07 18:06:49 +00:00
``encoding`` will be removed in Flask 2.1. The file must be text
mode, or binary mode with UTF-8 bytes.
2019-11-28 11:40:45 +00:00
"""
2022-11-07 18:06:49 +00:00
if app is not None:
import warnings
2019-11-28 11:40:45 +00:00
warnings.warn(
2022-11-07 18:06:49 +00:00
"The 'app' parameter is deprecated and will be removed in"
" Flask 2.3. Call 'app.json.load' directly instead.",
DeprecationWarning,
stacklevel=2,
)
2022-11-07 18:06:49 +00:00
else:
app = current_app
2022-11-07 18:06:49 +00:00
if app:
return app.json.load(fp, **kwargs)
2019-11-28 11:40:45 +00:00
return _json.load(fp, **kwargs)
def htmlsafe_dumps(obj: t.Any, **kwargs: t.Any) -> str:
"""Serialize an object to a string of JSON with :func:`dumps`, then
replace HTML-unsafe characters with Unicode escapes and mark the
result safe with :class:`~markupsafe.Markup`.
2019-11-28 11:40:45 +00:00
This is available in templates as the ``|tojson`` filter.
2019-11-28 11:40:45 +00:00
The returned string is safe to render in HTML documents and
``<script>`` tags. The exception is in HTML attributes that are
double quoted; either use single quotes or the ``|forceescape``
filter.
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
.. deprecated:: 2.2
Will be removed in Flask 2.3. This is built-in to Jinja now.
.. versionchanged:: 2.0
Uses :func:`jinja2.utils.htmlsafe_json_dumps`. The returned
value is marked safe by wrapping in :class:`~markupsafe.Markup`.
2019-11-28 11:40:45 +00:00
.. versionchanged:: 0.10
Single quotes are escaped, making this safe to use in HTML,
``<script>`` tags, and single-quoted attributes without further
escaping.
2019-11-28 11:40:45 +00:00
"""
2022-11-07 18:06:49 +00:00
import warnings
warnings.warn(
"'htmlsafe_dumps' is deprecated and will be removed in Flask"
" 2.3. Use 'jinja2.utils.htmlsafe_json_dumps' instead.",
DeprecationWarning,
stacklevel=2,
)
return _jinja_htmlsafe_dumps(obj, dumps=dumps, **kwargs)
2019-11-28 11:40:45 +00:00
def htmlsafe_dump(obj: t.Any, fp: t.IO[str], **kwargs: t.Any) -> None:
"""Serialize an object to JSON written to a file object, replacing
HTML-unsafe characters with Unicode escapes. See
:func:`htmlsafe_dumps` and :func:`dumps`.
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
.. deprecated:: 2.2
Will be removed in Flask 2.3.
"""
import warnings
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
warnings.warn(
"'htmlsafe_dump' is deprecated and will be removed in Flask"
" 2.3. Use 'jinja2.utils.htmlsafe_json_dumps' instead.",
DeprecationWarning,
stacklevel=2,
)
fp.write(htmlsafe_dumps(obj, **kwargs))
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
def jsonify(*args: t.Any, **kwargs: t.Any) -> Response:
"""Serialize the given arguments as JSON, and return a
:class:`~flask.Response` object with the ``application/json``
mimetype. A dict or list returned from a view will be converted to a
JSON response automatically without needing to call this.
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
This requires an active request or application context, and calls
:meth:`app.json.response() <flask.json.provider.JSONProvider.response>`.
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
In debug mode, the output is formatted with indentation to make it
easier to read. This may also be controlled by the provider.
2022-11-07 18:06:49 +00:00
Either positional or keyword arguments can be given, not both.
If no arguments are given, ``None`` is serialized.
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
:param args: A single value to serialize, or multiple values to
treat as a list to serialize.
:param kwargs: Treat as a dict to serialize.
2019-11-28 11:40:45 +00:00
2022-11-07 18:06:49 +00:00
.. versionchanged:: 2.2
Calls ``current_app.json.response``, allowing an app to override
the behavior.
2019-11-28 11:40:45 +00:00
.. versionchanged:: 2.0.2
:class:`decimal.Decimal` is supported by converting to a string.
2019-11-28 11:40:45 +00:00
.. versionchanged:: 0.11
2022-11-07 18:06:49 +00:00
Added support for serializing top-level arrays. This was a
security risk in ancient browsers. See :ref:`security-json`.
2019-11-28 11:40:45 +00:00
.. versionadded:: 0.2
"""
2022-11-07 18:06:49 +00:00
return current_app.json.response(*args, **kwargs)