美文网首页
Flask设置返回json格式数据

Flask设置返回json格式数据

作者: 真老根儿 | 来源:发表于2018-07-23 21:06 被阅读0次

    问题描述

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

    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()
    

    这样访问会直接提示

    TypeError: 'dict' object is not callable
    

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

    解决方法

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

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

    使用标准库json

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

    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模块:

    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

    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()

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

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

    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,如:

    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()
    

    本文转载自Flask设置返回json格式数据

    相关文章

      网友评论

          本文标题:Flask设置返回json格式数据

          本文链接:https://www.haomeiwen.com/subject/ichsmftx.html