- 在flask中已经内置了json的处理
- jsonify的其他使用方法
- flask中的原始基类提供的todict方法
- 重写jsonify中方法,兼容序列化对象
- 打造高可用的序列化器,结合上面对象转字典,完美解决jsonify可序列化对象
在flask中已经内置了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()
jsonify的其他使用方法
#这里数据库模型使用的SQLAlchemy
class User(Base):
id = Column(Integer, primary_key=True)
nickname = Column(String(24), unique=True)
_password = Column('password', String(100))
一般的玩法就是把对象属性给个都取出来,存放在字典里面,然后用jsonify序列化。这个玩多了,开发也差不多累了,心塞。因为这个方法不能直接序列化对象,那就想办法让它可以就牛逼了。
这里面有两个过程可以优化:
- 对象快速转字典
- 对象嵌套快熟序列化
flask中的原始基类提供的todict方法
需要主要的是,它只能把实例属性转化为字段,其他属性并没有。并且我们通常需要对数据模型进行序列化,如果通过这样方式转化里面有很多用不着的属性没办法去掉(这里有点view-model感觉了)。 解决方案demo:
class User(Base):
id = Column(Integer, primary_key=True)
nickname = Column(String(24), unique=True)
_password = Column('password', String(100))
#返回对象中的每个属性
def keys(self):
#return ['id','nickname']也可以指定序列化指定的字段
return self.fields
#通过对象的每个属性获取对应的值
def __getitem__(self, item):
return getattr(self, item)
最后用dict(user)即可
重写jsonify中方法,兼容序列化对象
解析JSONEncoder中default方法,每当调用jsonify的时候发现有不可序列化的数据时候,会触发此方法,并且是递归调用的。看源码不难理解里面内容。
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)
打造高可用的序列化器,结合上面对象转字典,完美解决jsonify可序列化对象
from flask import Flask as _Flask
from flask.json import JSONEncoder as _JSONEncoder
from datetime import date
#继承_JSONEncoder重写default,每当发送有不能序列化的类型时,在这里就可以参考源码进行添加即可。
class JSONEncoder(_JSONEncoder):
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 Error()
#重写flask,把新的JSONEncoder赋值给flask对象,这样新的才能生效
class Flask(_Flask):
json_encoder = JSONEncoder