Flask设置返回json格式数据

问题描述

在Flask中直接返回listdict是不行的,如

Python

Python
from <span class="wp_keywordlink_affiliate"><a href="https://www.168seo.cn/tag/flask" title="View all posts in flask" target="_blank">flask</a></span> import Flask app = Flask(__name__) @app.route('/') def root(): t = { 'a': 1, 'b': 2, 'c': [3, 4, 5] } return t if __name__ == '__main__': app.debug = True app.run()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from flask import Flask
 
app = Flask ( __name__ )
 
 
@ app . route ( '/' )
def root ( ) :
     t = {
         'a' : 1 ,
         'b' : 2 ,
         'c' : [ 3 , 4 , 5 ]
     }
     return t
 
if __name__ == '__main__' :
     app . debug = True
     app . run ( )
 

这样访问会直接提示

Python
TypeError: 'dict' object is not callable
1
2
TypeError : 'dict' object is not callable
 

其原因是Flask并不会将listdict默认转换为json格式。

解决方法

HTTP返回json格式数据主要有两个方面:

  1. 数据本身为json格式;
  2. Content-Type声明为json格式。

使用标准库json

比较常见的是采用标准库json进行格式转换:

Python

Python
from <span class="wp_keywordlink_affiliate"><a href="https://www.168seo.cn/tag/flask" title="View all posts in flask" target="_blank">flask</a></span> import Flask import json app = Flask(__name__) @app.route('/') def root(): t = { 'a': 1, 'b': 2, 'c': [3, 4, 5] } return json.dumps(t) if __name__ == '__main__': app.debug = True app.run()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from flask import Flask
import json
 
app = Flask ( __name__ )
 
 
@ app . route ( '/' )
def root ( ) :
     t = {
         'a' : 1 ,
         'b' : 2 ,
         'c' : [ 3 , 4 , 5 ]
     }
     return json . dumps ( t )
 
if __name__ == '__main__' :
     app . debug = True
     app . run ( )
 

这样当访问时即能够正常得到json数据。但这么做有一个缺点,就是HTTP返回的Content-Type仍然是text/html,即HTTP认为内容是HTML。

声明Content-Type为json格式

在上面的解决方法上作一个加强,手动指定其Content-Typeapplication/json,通常采用的是修改Flask中的Response模块:

Python

Python
from flask import Flask, Response import json app = Flask(__name__) @app.route('/') def root(): t = { 'a': 1, 'b': 2, 'c': [3, 4, 5] } return Response(json.dumps(t), mimetype='application/json') if __name__ == '__main__': app.debug = True app.run()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from flask import Flask , Response
import json
 
app = Flask ( __name__ )
 
 
@ app . route ( '/' )
def root ( ) :
     t = {
         'a' : 1 ,
         'b' : 2 ,
         'c' : [ 3 , 4 , 5 ]
     }
     return Response ( json . dumps ( t ) , mimetype = 'application/json' )
 
if __name__ == '__main__' :
     app . debug = True
     app . run ( )
 

这样不仅HTTP返回的内容是json,而且返回的Content-Type也是application/json了。

使用Flask的jsonify模块

实际上flask已经为json准备了专门的模块:jsonifyjsonify不仅会将内容转换为json,而且也会修改Content-Typeapplication/json

Python

Python
from flask import Flask, jsonify app = Flask(__name__) @app.route('/') def root(): t = { 'a': 1, 'b': 2, 'c': [3, 4, 5] } return jsonify(t) if __name__ == '__main__': app.debug = True app.run()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from flask import Flask , jsonify
 
app = Flask ( __name__ )
 
 
@ app . route ( '/' )
def root ( ) :
     t = {
         'a' : 1 ,
         'b' : 2 ,
         'c' : [ 3 , 4 , 5 ]
     }
     return jsonify ( t )
 
if __name__ == '__main__' :
     app . debug = True
     app . run ( )
 

自定义Flask的Response,使用force_type()(2017.11.9更新)

对于某些特殊的情况,可能并不想每个返回json数据的方法都使用jsonify()包起来,那有没有什么“非侵入式”的方法实现jsonify()的功能呢?其实是有的,不过这个方法相对比较高端。

Flask返回的内容实际是Response对象,return语句的内容实际是交给Response处理后才输出由HTTP返回的;也就是说,之前直接返回dict报错TypeError: 'dict' object is not callable也是Response干的。那么只需要在Response处理如dict等“非法”数据是,告诉Response该怎么做就好了,这里就是用到了其force_type()方法了,所有不能处理的数据,都由force_type()方法尝试处理后,再决定报错或通过。直接看例子吧。

Python
from flask import Flask, Response, jsonify class MyResponse(Response): @classmethod def force_type(cls, response, environ=None): if isinstance(response, (list, dict)): response = jsonify(response) return super(Response, cls).force_type(response, environ) app = Flask(__name__) app.response_class = MyResponse @app.route('/') def root(): t = { 'a': 1, 'b': 2, 'c': [3, 4, 5] } return t if __name__ == '__main__': app.debug = True app.run()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from flask import Flask , Response , jsonify
 
class MyResponse ( Response ) :
     @ classmethod
     def force_type ( cls , response , environ = None ) :
         if isinstance ( response , ( list , dict ) ) :
             response = jsonify ( response )
         return super ( Response , cls ) . force_type ( response , environ )
 
app = Flask ( __name__ )
app . response_class = MyResponse
 
@ app . route ( '/' )
def root ( ) :
     t = {
         'a' : 1 ,
         'b' : 2 ,
         'c' : [ 3 , 4 , 5 ]
     }
     return t
 
if __name__ == '__main__' :
     app . debug = True
     app . run ( )
 

或者还可以以继承的方式来实现自定义Response,如:

Python

Python
from flask import Flask, Response, jsonify class MyResponse(Response): @classmethod def force_type(cls, response, environ=None): if isinstance(response, (list, dict)): response = jsonify(response) return super(Response, cls).force_type(response, environ) class MyFlask(Flask): response_class = MyResponse app = MyFlask(__name__) @app.route('/') def root(): t = { 'a': 1, 'b': 2, 'c': [3, 4, 5] } return t if __name__ == '__main__': app.debug = True app.run()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from flask import Flask , Response , jsonify
 
class MyResponse ( Response ) :
     @ classmethod
     def force_type ( cls , response , environ = None ) :
         if isinstance ( response , ( list , dict ) ) :
             response = jsonify ( response )
         return super ( Response , cls ) . force_type ( response , environ )
 
class MyFlask ( Flask ) :
     response_class = MyResponse
 
app = MyFlask ( __name__ )
 
@ app . route ( '/' )
def root ( ) :
     t = {
         'a' : 1 ,
         'b' : 2 ,
         'c' : [ 3 , 4 , 5 ]
     }
     return t
 
if __name__ == '__main__' :
     app . debug = True
     app . run ( )
 



  • zeropython 微信公众号 5868037 QQ号 5868037@qq.com QQ邮箱
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值