forked from orbit-oss/flask
deprecate JSON encoding options
make consistent with built-in json module
This commit is contained in:
parent
c43edfc7c0
commit
8b5f760b72
2 changed files with 54 additions and 49 deletions
|
|
@ -1,10 +1,11 @@
|
||||||
import io
|
import io
|
||||||
import json as _json
|
import json as _json
|
||||||
import uuid
|
import uuid
|
||||||
|
import warnings
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from jinja2 import Markup
|
from markupsafe import Markup
|
||||||
from werkzeug.http import http_date
|
from werkzeug.http import http_date
|
||||||
|
|
||||||
from ..globals import current_app
|
from ..globals import current_app
|
||||||
|
|
@ -17,33 +18,6 @@ except ImportError:
|
||||||
dataclasses = None
|
dataclasses = None
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
|
||||||
"dump",
|
|
||||||
"dumps",
|
|
||||||
"load",
|
|
||||||
"loads",
|
|
||||||
"htmlsafe_dump",
|
|
||||||
"htmlsafe_dumps",
|
|
||||||
"JSONDecoder",
|
|
||||||
"JSONEncoder",
|
|
||||||
"jsonify",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def _wrap_reader_for_text(fp, encoding):
|
|
||||||
if isinstance(fp.read(0), bytes):
|
|
||||||
fp = io.TextIOWrapper(io.BufferedReader(fp), encoding)
|
|
||||||
return fp
|
|
||||||
|
|
||||||
|
|
||||||
def _wrap_writer_for_text(fp, encoding):
|
|
||||||
try:
|
|
||||||
fp.write("")
|
|
||||||
except TypeError:
|
|
||||||
fp = io.TextIOWrapper(fp, encoding)
|
|
||||||
return fp
|
|
||||||
|
|
||||||
|
|
||||||
class JSONEncoder(_json.JSONEncoder):
|
class JSONEncoder(_json.JSONEncoder):
|
||||||
"""The default Flask JSON encoder. This one extends the default
|
"""The default Flask JSON encoder. This one extends the default
|
||||||
encoder by also supporting ``datetime``, ``UUID``, ``dataclasses``,
|
encoder by also supporting ``datetime``, ``UUID``, ``dataclasses``,
|
||||||
|
|
@ -83,7 +57,7 @@ class JSONEncoder(_json.JSONEncoder):
|
||||||
return dataclasses.asdict(o)
|
return dataclasses.asdict(o)
|
||||||
if hasattr(o, "__html__"):
|
if hasattr(o, "__html__"):
|
||||||
return str(o.__html__())
|
return str(o.__html__())
|
||||||
return _json.JSONEncoder.default(self, o)
|
return super().default(self, o)
|
||||||
|
|
||||||
|
|
||||||
class JSONDecoder(_json.JSONDecoder):
|
class JSONDecoder(_json.JSONDecoder):
|
||||||
|
|
@ -101,13 +75,9 @@ def _dump_arg_defaults(kwargs, app=None):
|
||||||
|
|
||||||
if app:
|
if app:
|
||||||
bp = app.blueprints.get(request.blueprint) if request else None
|
bp = app.blueprints.get(request.blueprint) if request else None
|
||||||
kwargs.setdefault(
|
cls = bp.json_encoder if bp and bp.json_encoder else app.json_encoder
|
||||||
"cls", bp.json_encoder if bp and bp.json_encoder else app.json_encoder
|
kwargs.setdefault("cls", cls)
|
||||||
)
|
kwargs.setdefault("ensure_ascii", app.config["JSON_AS_ASCII"])
|
||||||
|
|
||||||
if not app.config["JSON_AS_ASCII"]:
|
|
||||||
kwargs.setdefault("ensure_ascii", False)
|
|
||||||
|
|
||||||
kwargs.setdefault("sort_keys", app.config["JSON_SORT_KEYS"])
|
kwargs.setdefault("sort_keys", app.config["JSON_SORT_KEYS"])
|
||||||
else:
|
else:
|
||||||
kwargs.setdefault("sort_keys", True)
|
kwargs.setdefault("sort_keys", True)
|
||||||
|
|
@ -121,9 +91,8 @@ def _load_arg_defaults(kwargs, app=None):
|
||||||
|
|
||||||
if app:
|
if app:
|
||||||
bp = app.blueprints.get(request.blueprint) if request else None
|
bp = app.blueprints.get(request.blueprint) if request else None
|
||||||
kwargs.setdefault(
|
cls = bp.json_decoder if bp and bp.json_decoder else app.json_decoder
|
||||||
"cls", bp.json_decoder if bp and bp.json_decoder else app.json_decoder
|
kwargs.setdefault("cls", cls)
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
kwargs.setdefault("cls", JSONDecoder)
|
kwargs.setdefault("cls", JSONDecoder)
|
||||||
|
|
||||||
|
|
@ -152,8 +121,15 @@ def dumps(obj, app=None, **kwargs):
|
||||||
encoding = kwargs.pop("encoding", None)
|
encoding = kwargs.pop("encoding", None)
|
||||||
rv = _json.dumps(obj, **kwargs)
|
rv = _json.dumps(obj, **kwargs)
|
||||||
|
|
||||||
if encoding is not None and isinstance(rv, str):
|
if encoding is not None:
|
||||||
rv = rv.encode(encoding)
|
warnings.warn(
|
||||||
|
"'encoding' is deprecated and will be removed in 2.1.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
if isinstance(rv, str):
|
||||||
|
return rv.encode(encoding)
|
||||||
|
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
|
|
@ -162,9 +138,21 @@ def dump(obj, fp, app=None, **kwargs):
|
||||||
"""Like :func:`dumps` but writes into a file object."""
|
"""Like :func:`dumps` but writes into a file object."""
|
||||||
_dump_arg_defaults(kwargs, app=app)
|
_dump_arg_defaults(kwargs, app=app)
|
||||||
encoding = kwargs.pop("encoding", None)
|
encoding = kwargs.pop("encoding", None)
|
||||||
|
show_warning = encoding is not None
|
||||||
|
|
||||||
if encoding is not None:
|
try:
|
||||||
fp = _wrap_writer_for_text(fp, encoding)
|
fp.write("")
|
||||||
|
except TypeError:
|
||||||
|
show_warning = True
|
||||||
|
fp = io.TextIOWrapper(fp, encoding or "utf-8")
|
||||||
|
|
||||||
|
if show_warning:
|
||||||
|
warnings.warn(
|
||||||
|
"Writing to a binary file, and the 'encoding' argument, is"
|
||||||
|
" deprecated and will be removed in 2.1.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
|
||||||
_json.dump(obj, fp, **kwargs)
|
_json.dump(obj, fp, **kwargs)
|
||||||
|
|
||||||
|
|
@ -192,8 +180,16 @@ def loads(s, app=None, **kwargs):
|
||||||
_load_arg_defaults(kwargs, app=app)
|
_load_arg_defaults(kwargs, app=app)
|
||||||
encoding = kwargs.pop("encoding", None)
|
encoding = kwargs.pop("encoding", None)
|
||||||
|
|
||||||
if encoding is not None and isinstance(s, bytes):
|
if encoding is not None:
|
||||||
s = s.decode(encoding)
|
warnings.warn(
|
||||||
|
"'encoding' is deprecated and will be removed in 2.1. The"
|
||||||
|
" data must be a string or UTF-8 bytes.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
if isinstance(s, bytes):
|
||||||
|
s = s.decode(encoding)
|
||||||
|
|
||||||
return _json.loads(s, **kwargs)
|
return _json.loads(s, **kwargs)
|
||||||
|
|
||||||
|
|
@ -202,7 +198,18 @@ def load(fp, app=None, **kwargs):
|
||||||
"""Like :func:`loads` but reads from a file object."""
|
"""Like :func:`loads` but reads from a file object."""
|
||||||
_load_arg_defaults(kwargs, app=app)
|
_load_arg_defaults(kwargs, app=app)
|
||||||
encoding = kwargs.pop("encoding", None)
|
encoding = kwargs.pop("encoding", None)
|
||||||
fp = _wrap_reader_for_text(fp, encoding or "utf-8")
|
|
||||||
|
if encoding is not None:
|
||||||
|
warnings.warn(
|
||||||
|
"'encoding' is deprecated and will be removed in 2.1. The"
|
||||||
|
" file must be text mode, or binary mode with UTF-8 bytes.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
if isinstance(fp.read(0), bytes):
|
||||||
|
fp = io.TextIOWrapper(fp, encoding)
|
||||||
|
|
||||||
return _json.load(fp, **kwargs)
|
return _json.load(fp, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -241,7 +248,7 @@ def htmlsafe_dumps(obj, **kwargs):
|
||||||
|
|
||||||
def htmlsafe_dump(obj, fp, **kwargs):
|
def htmlsafe_dump(obj, fp, **kwargs):
|
||||||
"""Like :func:`htmlsafe_dumps` but writes into a file object."""
|
"""Like :func:`htmlsafe_dumps` but writes into a file object."""
|
||||||
fp.write(str(htmlsafe_dumps(obj, **kwargs)))
|
fp.write(htmlsafe_dumps(obj, **kwargs))
|
||||||
|
|
||||||
|
|
||||||
def jsonify(*args, **kwargs):
|
def jsonify(*args, **kwargs):
|
||||||
|
|
@ -293,7 +300,6 @@ def jsonify(*args, **kwargs):
|
||||||
|
|
||||||
.. versionadded:: 0.2
|
.. versionadded:: 0.2
|
||||||
"""
|
"""
|
||||||
|
|
||||||
indent = None
|
indent = None
|
||||||
separators = (",", ":")
|
separators = (",", ":")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -232,7 +232,6 @@ class TestJSON:
|
||||||
render = flask.render_template_string
|
render = flask.render_template_string
|
||||||
rv = flask.json.htmlsafe_dumps("</script>")
|
rv = flask.json.htmlsafe_dumps("</script>")
|
||||||
assert rv == '"\\u003c/script\\u003e"'
|
assert rv == '"\\u003c/script\\u003e"'
|
||||||
assert type(rv) is str
|
|
||||||
rv = render('{{ "</script>"|tojson }}')
|
rv = render('{{ "</script>"|tojson }}')
|
||||||
assert rv == '"\\u003c/script\\u003e"'
|
assert rv == '"\\u003c/script\\u003e"'
|
||||||
rv = render('{{ "<\0/script>"|tojson }}')
|
rv = render('{{ "<\0/script>"|tojson }}')
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue