前言flask 有个jsonify() 函数,如果返回的是一个字典,那么调用 jsonify 创建一个响应对象。 关于响应视图函数的返回值会自动转换为一个响应对象。 如果返回值是一个字符串,那么会被 转换为一个包含作为响应体的字符串、一个 200 OK 出错代码 和一个 text/html 类型的响应对象。 如果返回值是一个字典,那么会调用 jsonify() 来产生一个响应。以下是转换的规则: 如果视图返回的是一个响应对象,那么就直接返回它。 如果返回的是一个字符串,那么根据这个字符串和缺省参数生成一个用于返回的 响应对象。 如果返回的是一个字典,那么调用 jsonify 创建一个响应对象。 如果返回的是一个元组,那么元组中的项目可以提供额外的信息。元组中必须至少 包含一个项目,且项目应当由 (response, status) 、 (response, headers) 或者 (response, status, headers) 组成。status 的值会重载状态代码, headers 是一个由额外头部值组成的列表 或字典。 如果以上都不是,那么 Flask 会假定返回值是一个有效的 WSGI 应用并把它转换为 一个响应对象。
jsonify() 响应对象如果返回的是一个字典,那么调用 jsonify 创建一个响应对象 先看一个示例 from flask import Flask, jsonify app = Flask(__name__)
@app.route('/json', methods=['GET']) def json_demo(): return { "username": 'yoyo', "email": "111@qq.com" }
if __name__ == '__main__': app.run()
接口返回 GET http://127.0.0.1:5000/json
HTTP/1.0 200 OK Content-Type: application/json Content-Length: 51 Server: Werkzeug/2.0.2 Python/3.8.5 Date: Thu, 13 Oct 2022 02:49:38 GMT
{ "email": "111@qq.com", "username": "yoyo" }
接口返回的是一个dict, 那么这时候会自动调用 jsonify 创建一个响应对象转成json格式,并且在返回头部带上Content-Type: application/json 我们也可以返回jsonify()函数,里面传一个字典,或者键值对的参数 from flask import Flask, jsonify app = Flask(__name__)
@app.route('/json1', methods=['GET']) def json_demo1(): return jsonify({ "username": 'yoyo', "email": "111@qq.com" })
@app.route('/json2', methods=['GET']) def json_demo2(): return jsonify( username="yoyo", email="111@qq.com" )
if __name__ == '__main__': app.run()
以上两种方式返回的结果都是 Content-Type: application/json Content-Length: 51 Server: Werkzeug/2.0.2 Python/3.8.5 Date: Thu, 13 Oct 2022 02:56:15 GMT
{ "email": "111@qq.com", "username": "yoyo" }
返回json字符串如果返回的是一个字符串,那么根据这个字符串和缺省参数生成一个用于返回的 响应对象。 我们试试自己返回一个json字符串,看看和jsonfy()处理过的有什么不一样 from flask import Flask, jsonify, json app = Flask(__name__)
@app.route('/json3', methods=['GET']) def json_demo3(): return json.dumps({ "username": 'yoyo', "email": "111@qq.com" })
if __name__ == '__main__': app.run()
接口返回内容 HTTP/1.0 200 OK Content-Type: text/html; charset=utf-8 Content-Length: 43 Server: Werkzeug/2.0.2 Python/3.8.5 Date: Thu, 13 Oct 2022 03:05:05 GMT
{"email": "111@qq.com", "username": "yoyo"}
此时返回的”Content-Type”类型是”text/html; charset=utf-8”,它是以文本的方式返回的,并不是以json方式返回,所以需要我们自己手动再加一个返回头部类型 @app.route('/json3', methods=['GET']) def json_demo3(): return json.dumps({ "username": 'yoyo', "email": "111@qq.com" }), {"Content-Type": "application/json"}
改成上面的代码,才会返回"Content-Type": "application/json" 也就是说jsonify() 函数帮我们在返回头部自动带上"Content-Type": "application/json" , 简化了操作。 jsonify() 源码解读先看源码内容 def jsonify(*args: t.Any, **kwargs: t.Any) -> "Response": """Serialize data to JSON and wrap it in a :class:`~flask.Response` with the :mimetype:`application/json` mimetype.
Uses :func:`dumps` to serialize the data, but ``args`` and ``kwargs`` are treated as data rather than arguments to :func:`json.dumps`.
1. Single argument: Treated as a single value. 2. Multiple arguments: Treated as a list of values. ``jsonify(1, 2, 3)`` is the same as ``jsonify([1, 2, 3])``. 3. Keyword arguments: Treated as a dict of values. ``jsonify(data=data, errors=errors)`` is the same as ``jsonify({"data": data, "errors": errors})``. 4. Passing both arguments and keyword arguments is not allowed as it's not clear what should happen.
.. code-block:: python
from flask import jsonify
@app.route("/users/me") def get_current_user(): return jsonify( username=g.user.username, email=g.user.email, id=g.user.id, )
Will return a JSON response like this:
.. code-block:: javascript
{ "username": "admin", "email": "admin@localhost", "id": 42 }
The default output omits indents and spaces after separators. In debug mode or if :data:`JSONIFY_PRETTYPRINT_REGULAR` is ``True``, the output will be formatted to be easier to read.
.. versionchanged:: 2.0.2 :class:`decimal.Decimal` is supported by converting to a string.
.. versionchanged:: 0.11 Added support for serializing top-level arrays. This introduces a security risk in ancient browsers. See :ref:`security-json`.
.. versionadded:: 0.2 """ indent = None separators = (",", ":")
if current_app.config["JSONIFY_PRETTYPRINT_REGULAR"] or current_app.debug: 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] else: data = args or kwargs
return current_app.response_class( f"{dumps(data, indent=indent, separators=separators)}\n", mimetype=current_app.config["JSONIFY_MIMETYPE"], )
大概翻译下,jsonify 的作用是把数据序列化成JSON,并且在声明返回头部application/json ,它返回一个Response 对象 它使用json.dumps 序列化数据, 但是 args 和 kwargs 会被作为数据,而不是参数 1.如果是单个参数 jsonify('xx')
那么返回 Content-Type: application/json
"xx"
2.如果是多个参数 jsonify(1, 2, 3)
那么等价于 jsonify([1, 2, 3])
都会返回 Content-Type: application/json
[ 1, 2, 3 ]
3.关键字参数 jsonify(data=data, errors=errors)
等价于 jsonify({"data": data, "errors": errors})
4.不允许同时传递args`参数和 kwargs``关键字参数,因为不清楚会发生什么. 默认情况下JSON输出会省略在分隔符后缩进和空格,起到了压缩数据的作用。(实际上就是用了 json.dumps(data, separators=(',’, ':’)) 处理。) 在debug模式或者我们设置了全局配置:JSONIFY_PRETTYPRINT_REGULAR 为 True ,输出将被格式化以便于阅读。 示例,debug为False @app.route('/json1', methods=['GET']) def json_demo1(): return jsonify(username='yoyo',email="111@qq.com")
if __name__ == '__main__': app.run(debug=False)
启动日志看到debug模式关闭了 * Serving Flask app 'app' (lazy loading) * Environment: development * Debug mode: off
次数输出的json格式会被去掉空格和缩进,可以起到压缩数据作用 Content-Type: application/json
{"email":"111@qq.com","username":"yoyo"}
为了方便阅读,我们可以开启debug模式,或者添加全局配置JSONIFY_PRETTYPRINT_REGULAR 为 True if __name__ == '__main__': app.run(debug=True)
启动日志 * Serving Flask app 'app' (lazy loading) * Environment: development * Debug mode: on
此时返回的json格式就是被美化过 {"email":"111@qq.com","username":"yoyo"}
其原理实际上就是用了 json.dumps()的 indent和 separators=(',’, ':’)处理 使用总结总的来说有以下几点功能 1.如果返回值是一个字典,那么会调用 jsonify() 来产生一个响应 2.jsonify 返回的Response的headers属性为:Content-Type: application/json ,是标准的json格式。 3.jsonify自动去除了JSON格式中逗号冒号间的空格,起到了压缩数据的作用。 2022年第 2 期《Python 测试平台开发》进阶课程(10月30号开学)
|