Add support for serializing top-level arrays to JSON

Fix #170, #248, #510, #673, #1177
This commit is contained in:
Jeff Widman 2015-12-30 03:11:53 -08:00
parent f17e6061fc
commit daceb3e3a0
5 changed files with 114 additions and 115 deletions

View file

@ -199,10 +199,22 @@ def htmlsafe_dump(obj, fp, **kwargs):
def jsonify(*args, **kwargs):
"""Creates a :class:`~flask.Response` with the JSON representation of
the given arguments with an :mimetype:`application/json` mimetype. The
arguments to this function are the same as to the :class:`dict`
constructor.
"""This function wraps :func:`dumps` to add a few enhancements that make
life easier. It turns the JSON output into a :class:`~flask.Response`
object with the :mimetype:`application/json` mimetype. For convenience, it
also converts multiple arguments into an array or multiple keyword arguments
into a dict. This means that both ``jsonify(1,2,3)`` and
``jsonify([1,2,3])`` serialize to ``[1,2,3]``.
For clarity, the JSON serialization behavior has the following differences
from :func:`dumps`:
1. Single argument: Passed straight through to :func:`dumps`.
2. Multiple arguments: Converted to an array before being passed to
:func:`dumps`.
3. Multiple keyword arguments: Converted to a dict before being passed to
:func:`dumps`.
4. Both args and kwargs: Behavior undefined and will throw an exception.
Example usage::
@ -222,8 +234,10 @@ def jsonify(*args, **kwargs):
"id": 42
}
For security reasons only objects are supported toplevel. For more
information about this, have a look at :ref:`json-security`.
.. versionchanged:: 1.0
Added support for serializing top-level arrays. This introduces a
security risk in ancient browsers. See :ref:`json_security` for details.
This function's response will be pretty printed if it was not requested
with ``X-Requested-With: XMLHttpRequest`` to simplify debugging unless
@ -242,11 +256,21 @@ def jsonify(*args, **kwargs):
indent = 2
separators = (', ', ': ')
if args and kwargs:
raise TypeError(
"jsonify() behavior undefined when passed both args and kwargs"
)
elif len(args) == 1: # single args are passed directly to dumps()
data = args[0]
elif args: # convert multiple args into an array
data = list(args)
else: # convert kwargs to a dict
data = dict(kwargs)
# Note that we add '\n' to end of response
# (see https://github.com/mitsuhiko/flask/pull/1262)
rv = current_app.response_class(
(dumps(dict(*args, **kwargs), indent=indent, separators=separators),
'\n'),
(dumps(data, indent=indent, separators=separators), '\n'),
mimetype='application/json')
return rv