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 | ||||
|     specify extra files that will trigger the reloader on change. | ||||
|     :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 | ||||
| .. _#2957: https://github.com/pallets/flask/issues/2957 | ||||
|  |  | |||
|  | @ -679,23 +679,26 @@ See :ref:`error-handlers` for more details. | |||
| About Responses | ||||
| --------------- | ||||
| 
 | ||||
| The return value from a view function is automatically converted into a | ||||
| response object for you.  If the return value is a string it's converted | ||||
| into a response object with the string as response body, a ``200 OK`` | ||||
| status code and a :mimetype:`text/html` mimetype. | ||||
| The logic that Flask applies to converting return values into | ||||
| response objects is as follows: | ||||
| The return value from a view function is automatically converted into | ||||
| a response object for you. If the return value is a string it's | ||||
| converted into a response object with the string as response body, a | ||||
| ``200 OK`` status code and a :mimetype:`text/html` mimetype. If the | ||||
| return value is a dict, :func:`jsonify` is called to produce a response. | ||||
| 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 | ||||
|     returned from the view. | ||||
| 2.  If it's a string, a response object is created with that data and the | ||||
|     default parameters. | ||||
| 3.  If a tuple is returned the items in the tuple can provide extra information. | ||||
|     Such tuples have to be in the form ``(response, status, headers)``, | ||||
|     ``(response, headers)`` or ``(response, status)`` where at least one item | ||||
|     has to be in the tuple. The ``status`` value will override the status code | ||||
|     and ``headers`` can be a list or dictionary of additional header values. | ||||
| 4.  If none of that works, Flask will assume the return value is a | ||||
| 2.  If it's a string, a response object is created with that data and | ||||
|     the default parameters. | ||||
| 3.  If it's a dict, a response object is created using ``jsonify``. | ||||
| 4.  If a tuple is returned the items in the tuple can provide extra | ||||
|     information. Such tuples have to be in the form | ||||
|     ``(response, status)``, ``(response, headers)``, or | ||||
|     ``(response, status, headers)``. The ``status`` value will override | ||||
|     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. | ||||
| 
 | ||||
| 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' | ||||
|         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 | ||||
|  |  | |||
|  | @ -44,6 +44,7 @@ from .helpers import ( | |||
|     url_for, | ||||
|     get_load_dotenv, | ||||
| ) | ||||
| from .json import jsonify | ||||
| from .logging import create_logger | ||||
| from .sessions import SecureCookieSessionInterface | ||||
| from .signals import ( | ||||
|  | @ -2001,6 +2002,9 @@ class Flask(_PackageBoundObject): | |||
|             ``bytes`` (``str`` in Python 2) | ||||
|                 A response object is created with the bytes as the body. | ||||
| 
 | ||||
|             ``dict`` | ||||
|                 A dictionary that will be jsonify'd before being returned. | ||||
| 
 | ||||
|             ``tuple`` | ||||
|                 Either ``(body, status, headers)``, ``(body, status)``, or | ||||
|                 ``(body, headers)``, where ``body`` is any of the other types | ||||
|  | @ -2064,6 +2068,8 @@ class Flask(_PackageBoundObject): | |||
|                 # special logic | ||||
|                 rv = self.response_class(rv, status=status, headers=headers) | ||||
|                 status = headers = None | ||||
|             elif isinstance(rv, dict): | ||||
|                 rv = jsonify(rv) | ||||
|             else: | ||||
|                 # evaluate a WSGI callable, or coerce a different response | ||||
|                 # class to the correct type | ||||
|  |  | |||
|  | @ -1147,8 +1147,12 @@ def test_response_types(app, client): | |||
|     def from_wsgi(): | ||||
|         return NotFound() | ||||
| 
 | ||||
|     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") | ||||
|     @app.route('/dict') | ||||
|     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") | ||||
|     assert rv.data == b"Meh" | ||||
|  | @ -1181,6 +1185,10 @@ def test_response_types(app, client): | |||
|     assert b"Not Found" in rv.data | ||||
|     assert rv.status_code == 404 | ||||
| 
 | ||||
|     rv = client.get('/dict') | ||||
|     assert rv.json == {"foo": "bar"} | ||||
|     assert rv.status_code == 201 | ||||
| 
 | ||||
| 
 | ||||
| def test_response_type_errors(): | ||||
|     app = flask.Flask(__name__) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue