mirror of https://github.com/pallets/flask.git
Merge pull request #3111 from pgjones/master
Allow dictionaries return values as JSON
This commit is contained in:
commit
855d59b68b
|
|
@ -52,6 +52,10 @@ Unreleased
|
||||||
- Add an ``--extra-files`` option to the ``flask run`` CLI command to
|
- Add an ``--extra-files`` option to the ``flask run`` CLI command to
|
||||||
specify extra files that will trigger the reloader on change.
|
specify extra files that will trigger the reloader on change.
|
||||||
:issue:`2897`
|
:issue:`2897`
|
||||||
|
- Allow returning a dictionary from a view function. Similar to how
|
||||||
|
returning a string will produce a ``text/html`` response, returning
|
||||||
|
a dict will call ``jsonify`` to produce a ``application/json``
|
||||||
|
response. :pr:`3111`
|
||||||
|
|
||||||
.. _#2935: https://github.com/pallets/flask/issues/2935
|
.. _#2935: https://github.com/pallets/flask/issues/2935
|
||||||
.. _#2957: https://github.com/pallets/flask/issues/2957
|
.. _#2957: https://github.com/pallets/flask/issues/2957
|
||||||
|
|
|
||||||
|
|
@ -679,23 +679,26 @@ See :ref:`error-handlers` for more details.
|
||||||
About Responses
|
About Responses
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
The return value from a view function is automatically converted into a
|
The return value from a view function is automatically converted into
|
||||||
response object for you. If the return value is a string it's converted
|
a response object for you. If the return value is a string it's
|
||||||
into a response object with the string as response body, a ``200 OK``
|
converted into a response object with the string as response body, a
|
||||||
status code and a :mimetype:`text/html` mimetype.
|
``200 OK`` status code and a :mimetype:`text/html` mimetype. If the
|
||||||
The logic that Flask applies to converting return values into
|
return value is a dict, :func:`jsonify` is called to produce a response.
|
||||||
response objects is as follows:
|
The logic that Flask applies to converting return values into response
|
||||||
|
objects is as follows:
|
||||||
|
|
||||||
1. If a response object of the correct type is returned it's directly
|
1. If a response object of the correct type is returned it's directly
|
||||||
returned from the view.
|
returned from the view.
|
||||||
2. If it's a string, a response object is created with that data and the
|
2. If it's a string, a response object is created with that data and
|
||||||
default parameters.
|
the default parameters.
|
||||||
3. If a tuple is returned the items in the tuple can provide extra information.
|
3. If it's a dict, a response object is created using ``jsonify``.
|
||||||
Such tuples have to be in the form ``(response, status, headers)``,
|
4. If a tuple is returned the items in the tuple can provide extra
|
||||||
``(response, headers)`` or ``(response, status)`` where at least one item
|
information. Such tuples have to be in the form
|
||||||
has to be in the tuple. The ``status`` value will override the status code
|
``(response, status)``, ``(response, headers)``, or
|
||||||
and ``headers`` can be a list or dictionary of additional header values.
|
``(response, status, headers)``. The ``status`` value will override
|
||||||
4. If none of that works, Flask will assume the return value is a
|
the status code and ``headers`` can be a list or dictionary of
|
||||||
|
additional header values.
|
||||||
|
5. If none of that works, Flask will assume the return value is a
|
||||||
valid WSGI application and convert that into a response object.
|
valid WSGI application and convert that into a response object.
|
||||||
|
|
||||||
If you want to get hold of the resulting response object inside the view
|
If you want to get hold of the resulting response object inside the view
|
||||||
|
|
@ -717,6 +720,39 @@ return it::
|
||||||
resp.headers['X-Something'] = 'A value'
|
resp.headers['X-Something'] = 'A value'
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
|
||||||
|
APIs with JSON
|
||||||
|
``````````````
|
||||||
|
|
||||||
|
A common response format when writing an API is JSON. It's easy to get
|
||||||
|
started writing such an API with Flask. If you return a ``dict`` from a
|
||||||
|
view, it will be converted to a JSON response.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
@app.route("/me")
|
||||||
|
def me_api():
|
||||||
|
user = get_current_user()
|
||||||
|
return {
|
||||||
|
"username": user.username,
|
||||||
|
"theme": user.theme,
|
||||||
|
"image": url_for("user_image", filename=user.image),
|
||||||
|
}
|
||||||
|
|
||||||
|
Depending on your API design, you may want to create JSON responses for
|
||||||
|
types other than ``dict``. In that case, use the
|
||||||
|
:func:`~flask.json.jsonify` function, which will serialize any supported
|
||||||
|
JSON data type. Or look into Flask community extensions that support
|
||||||
|
more complex applications.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
@app.route("/users")
|
||||||
|
def users_api():
|
||||||
|
users = get_all_users()
|
||||||
|
return jsonify([user.to_json() for user in users])
|
||||||
|
|
||||||
|
|
||||||
.. _sessions:
|
.. _sessions:
|
||||||
|
|
||||||
Sessions
|
Sessions
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ from .helpers import (
|
||||||
url_for,
|
url_for,
|
||||||
get_load_dotenv,
|
get_load_dotenv,
|
||||||
)
|
)
|
||||||
|
from .json import jsonify
|
||||||
from .logging import create_logger
|
from .logging import create_logger
|
||||||
from .sessions import SecureCookieSessionInterface
|
from .sessions import SecureCookieSessionInterface
|
||||||
from .signals import (
|
from .signals import (
|
||||||
|
|
@ -2001,6 +2002,9 @@ class Flask(_PackageBoundObject):
|
||||||
``bytes`` (``str`` in Python 2)
|
``bytes`` (``str`` in Python 2)
|
||||||
A response object is created with the bytes as the body.
|
A response object is created with the bytes as the body.
|
||||||
|
|
||||||
|
``dict``
|
||||||
|
A dictionary that will be jsonify'd before being returned.
|
||||||
|
|
||||||
``tuple``
|
``tuple``
|
||||||
Either ``(body, status, headers)``, ``(body, status)``, or
|
Either ``(body, status, headers)``, ``(body, status)``, or
|
||||||
``(body, headers)``, where ``body`` is any of the other types
|
``(body, headers)``, where ``body`` is any of the other types
|
||||||
|
|
@ -2064,6 +2068,8 @@ class Flask(_PackageBoundObject):
|
||||||
# special logic
|
# special logic
|
||||||
rv = self.response_class(rv, status=status, headers=headers)
|
rv = self.response_class(rv, status=status, headers=headers)
|
||||||
status = headers = None
|
status = headers = None
|
||||||
|
elif isinstance(rv, dict):
|
||||||
|
rv = jsonify(rv)
|
||||||
else:
|
else:
|
||||||
# evaluate a WSGI callable, or coerce a different response
|
# evaluate a WSGI callable, or coerce a different response
|
||||||
# class to the correct type
|
# class to the correct type
|
||||||
|
|
|
||||||
|
|
@ -1147,8 +1147,12 @@ def test_response_types(app, client):
|
||||||
def from_wsgi():
|
def from_wsgi():
|
||||||
return NotFound()
|
return NotFound()
|
||||||
|
|
||||||
assert client.get("/text").data == u"Hällo Wörld".encode("utf-8")
|
@app.route('/dict')
|
||||||
assert client.get("/bytes").data == u"Hällo Wörld".encode("utf-8")
|
def from_dict():
|
||||||
|
return {"foo": "bar"}, 201
|
||||||
|
|
||||||
|
assert client.get('/text').data == u'Hällo Wörld'.encode('utf-8')
|
||||||
|
assert client.get('/bytes').data == u'Hällo Wörld'.encode('utf-8')
|
||||||
|
|
||||||
rv = client.get("/full_tuple")
|
rv = client.get("/full_tuple")
|
||||||
assert rv.data == b"Meh"
|
assert rv.data == b"Meh"
|
||||||
|
|
@ -1181,6 +1185,10 @@ def test_response_types(app, client):
|
||||||
assert b"Not Found" in rv.data
|
assert b"Not Found" in rv.data
|
||||||
assert rv.status_code == 404
|
assert rv.status_code == 404
|
||||||
|
|
||||||
|
rv = client.get('/dict')
|
||||||
|
assert rv.json == {"foo": "bar"}
|
||||||
|
assert rv.status_code == 201
|
||||||
|
|
||||||
|
|
||||||
def test_response_type_errors():
|
def test_response_type_errors():
|
||||||
app = flask.Flask(__name__)
|
app = flask.Flask(__name__)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue