【问题标题】:How to return a dict as a JSON response from a Flask view?如何从 Flask 视图将字典作为 JSON 响应返回?
【发布时间】:2012-10-26 05:56:47
【问题描述】:

我有一个函数可以用 Pandas 分析 CSV 文件并生成带有摘要信息的字典。我想将结果作为 Flask 视图的响应返回。如何返回 JSON 响应?

@app.route("/summary")
def summary():
    d = make_summary()
    # send it back as json

【问题讨论】:

    标签: python json flask


    【解决方案1】:

    从 Flask 1.1.0 开始,视图可以直接返回 Python dict,Flask 会自动调用 jsonify

    @app.route("/summary")
    def summary():
        d = make_summary()
        return d
    

    如果您的 Flask 版本低于 1.1.0 或要返回不同的 JSON 可序列化对象,请导入并使用 jsonify

    from flask import jsonify
    
    @app.route("/summary")
    def summary():
        d = make_summary()
        return jsonify(d)
    

    【讨论】:

      【解决方案2】:

      jsonify 将您传递给 JSON 的数据序列化。如果您想自己序列化数据,请执行 jsonify 所做的操作,即使用 status=200mimetype='application/json' 构建响应。

      from flask import json
      
      @app.route('/summary')
      def summary():
          data = make_summary()
          response = app.response_class(
              response=json.dumps(data),
              status=200,
              mimetype='application/json'
          )
          return response
      

      【讨论】:

        【解决方案3】:

        将关键字参数传递给flask.jsonify,它们将作为 JSON 对象输出。

        @app.route('/_get_current_user')
        def get_current_user():
            return jsonify(
                username=g.user.username,
                email=g.user.email,
                id=g.user.id
            )
        
        {
            "username": "admin",
            "email": "admin@localhost",
            "id": 42
        }
        

        如果你已经有一个dict,你可以直接将它传递为jsonify(d)

        【讨论】:

          【解决方案4】:

          如果您出于某种原因不想使用jsonify,您可以手动执行它的操作。调用 flask.json.dumps 创建 JSON 数据,然后返回内容类型为 application/json 的响应。

          from flask import json
          
          @app.route('/summary')
          def summary():
              data = make_summary()
              response = app.response_class(
                  response=json.dumps(data),
                  mimetype='application/json'
              )
              return response
          

          flask.json 不同于内置的json 模块。如果可用,它将使用更快的 simplejson 模块,并支持与您的 Flask 应用程序的各种集成。

          【讨论】:

            【解决方案5】:

            要返回 JSON 响应并设置状态代码,您可以使用 make_response

            from flask import jsonify, make_response
            
            @app.route('/summary')
            def summary():
                d = make_summary()
                return make_response(jsonify(d), 200)
            

            灵感来自 Flask 问题跟踪器中的 comment

            【讨论】:

              【解决方案6】:

              从 Flask 1.1.0 版开始,if a view returns a dict it will be turned into a JSON response

              @app.route("/users", methods=['GET'])
              def get_user():
                  return {
                      "user": "John Doe",
                  }
              

              【讨论】:

                【解决方案7】:

                如果你想分析用户上传的文件,Flask quickstart 展示了如何从用户那里获取文件并访问它们。从request.files 获取文件并将其传递给摘要函数。

                from flask import request, jsonify
                from werkzeug import secure_filename
                
                @app.route('/summary', methods=['GET', 'POST'])
                def summary():
                    if request.method == 'POST':
                        csv = request.files['data']
                        return jsonify(
                            summary=make_summary(csv),
                            csv_name=secure_filename(csv.filename)
                        )
                
                    return render_template('submit_data.html')
                

                request.files'data' 键替换为 HTML 表单中输入的文件名。

                【讨论】:

                  【解决方案8】:

                  Flask 1.1.x 支持在不调用 jsonify 的情况下返回 JSON 字典。如果你想返回一个字典以外的东西,你仍然需要调用jsonify

                  @app.route("/")
                  def index():
                      return {
                          "api_stuff": "values",
                      }
                  

                  等价于

                  @app.route("/")
                  def index():
                      return jsonify({
                          "api_stuff": "values",
                      })
                  

                  查看添加此内容的拉取请求:https://github.com/pallets/flask/pull/3111

                  【讨论】:

                    【解决方案9】:

                    我使用装饰器返回jsonfiy 的结果。我认为当一个视图有多个返回时它更具可读性。这不支持返回像content, status 这样的元组,但我用app.errorhandler 处理返回错误状态。

                    import functools
                    from flask import jsonify
                    
                    def return_json(f):
                        @functools.wraps(f)
                        def inner(**kwargs):
                            return jsonify(f(**kwargs))
                    
                        return inner
                    
                    @app.route('/test/<arg>')
                    @return_json
                    def test(arg):
                        if arg == 'list':
                            return [1, 2, 3]
                        elif arg == 'dict':
                            return {'a': 1, 'b': 2}
                        elif arg == 'bool':
                            return True
                        return 'none of them'
                    

                    【讨论】:

                      【解决方案10】:

                      在 Flask 0.11 之前,jsonfiy 不允许直接返回数组。而是将列表作为关键字参数传递。

                      @app.route('/get_records')
                      def get_records():
                          results = [
                              {
                                "rec_create_date": "12 Jun 2016",
                                "rec_dietary_info": "nothing",
                                "rec_dob": "01 Apr 1988",
                                "rec_first_name": "New",
                                "rec_last_name": "Guy",
                              },
                              {
                                "rec_create_date": "1 Apr 2016",
                                "rec_dietary_info": "Nut allergy",
                                "rec_dob": "01 Feb 1988",
                                "rec_first_name": "Old",
                                "rec_last_name": "Guy",
                              },
                          ]
                          return jsonify(results=list)
                      

                      【讨论】:

                        【解决方案11】:

                        在 Flask 1.1 中,如果你返回一个字典,它会自动转换成 JSON。所以如果make_summary()返回一个字典,你可以

                        from flask import Flask
                        
                        app = Flask(__name__)
                        
                        @app.route('/summary')
                        def summary():
                            d = make_summary()
                            return d
                        

                        SO that asks about including the status code 已关闭,与此重复。因此,为了回答这个问题,您可以通过返回 (dict, int) 形式的元组来包含状态代码。 dict 转换为 JSON,int 将是 HTTP 状态代码。在没有任何输入的情况下,Status 是默认的 200。因此在上面的示例中,代码将为 200。在下面的示例中,它更改为 201。

                        from flask import Flask
                        
                        app = Flask(__name__)
                        
                        @app.route('/summary')
                        def summary():
                            d = make_summary()
                            return d, 201  # 200 is the default
                        

                        您可以使用

                        检查状态码
                        curl --request GET "http://127.0.0.1:5000/summary" -w "\ncode: %{http_code}\n\n"
                        

                        【讨论】:

                          【解决方案12】:

                          如果是dict,flask可以直接返回(1.0.2版)

                          def summary():
                              d = make_summary()
                              return d, 200
                          

                          【讨论】:

                            【解决方案13】:

                            使用 Flask 的基于类的视图时,答案是一样的。

                            from flask import Flask, request, jsonify
                            from flask.views import MethodView
                            
                            app = Flask(__name__)
                            
                            class Summary(MethodView):
                                def get(self):
                                    d = make_summary()
                                    return jsonify(d)
                            
                            app.add_url_rule('/summary/', view_func=Summary.as_view('summary'))
                            

                            【讨论】:

                              【解决方案14】:

                              要序列化一个对象,请使用flask 模块中的jsonify 对对象进行jsonify,默认情况下会序列化一个字典。此外,如果您正在处理文件,您可以随时使用make_response

                              【讨论】:

                              • 这并没有对现有答案增加太多,这些答案展示了如何使用 jsonifymake_response 并提供更深入的见解。
                              【解决方案15】:

                              我喜欢这种方式:

                                  @app.route("/summary")
                                  def summary():
                                      responseBody = { "message": "bla bla bla", "summary": make_summary() }
                                      return make_response(jsonify(responseBody), 200)
                              

                              【讨论】:

                              • 你为什么喜欢这样?是什么让这比仅仅返回responseBody 更好? (顺便说一句,最好按照 PEP-8 使用 snake_case)。
                              • 这对于代码审查来说更清楚,否则返回行将是一个难以阅读的长行。另外,我想通过这种方式我们可以选择编辑 HTTP 状态代码。
                              猜你喜欢
                              • 2021-12-26
                              • 1970-01-01
                              • 2016-01-01
                              • 2019-07-01
                              相关资源
                              最近更新 更多