jsonify的改进

一. json和jsonify

二. 改进的jsonify

三. 使用


一. json和jsonify

json.dumps需要指定返回类型:

    t = {
      #...
    }
    return Response(json.dumps(t), mimetype='application/json')

jsonify默认将返回的类型指定成了application/json :

    t = {
      #...
    }
    return jsonify(t), 200

但是在使用默认情况下, jsonify对于很多类型的数据是无法序列化的(当然json.dumps也不行), 比如时间类型的字典, model的实例对象.

二. 改进的jsonify

如果jsonify不知道如何序列化指定的对象, 程序便会调用JSONEncodedefualt方法:

# 源码部分
class JSONEncoder(_json.JSONEncoder):
    def default(self, o):
        # ...
        if isinstance(o, datetime):
            return http_date(o.utctimetuple())
        if isinstance(o, date):
            return http_date(o.timetuple())
        if isinstance(o, uuid.UUID):
            return str(o)
        if hasattr(o, '__html__'):
            return text_type(o.__html__())
        return _json.JSONEncoder.default(self, o)
    #...

其中参数o便是需要序列化的对象.
因此可以重新定义这个default方法, 使jsonify支持对sqlalchemy实例和datetime类型数据的序列化:

在合适的位置引入并重写:

from flask.json import JSONEncoder as _JSONEncoder
class JSONEncoder(_JSONEncoder):
    """重写对象序列化, 当默认jsonify无法序列化对象的时候将调用这里的default"""
    def default(self, o):
        if hasattr(o, 'keys') and hasattr(o, '__getitem__'):
            return dict(o)
        if isinstance(o, date):
            # 也可以序列化时间类型的对象
            return o.strftime('%Y-%m-%d')
        raise ServerError()
  • : dict(o)用到了对象转字典, 其中ServerError也是自定义的异常.

重写后必须指定flask的json_encoder:

from flask import Flask as _Flask
class Flask(_Flask):
    json_encoder = JSONEncoder

实例化flask对象的时候, 不要使用原版的Flask类, 而是使用刚刚改进后的class Flask(_Flask):., 直接app = Flask(__name__)即可.

三. 使用

改进后的jsonify已经支持对时间和model对象的序列化

from flask import jsonify

#...
    books = Book.query.all()
    return jsonify(books)