flask入门到起飞(十五)restful序列化进阶

96
aimaile
2018.11.03 22:42 字数 400

序列化

这个对于web开发来说算是必须课了,而且实现他们的方式方法还是很多,如原生的jsonify,还有其他的第三方框架也可以,不一一列举,这里来分享进阶玩法。

jsonify进阶玩法

#这里数据库模型使用的SQLAlchemy
class User(Base):
    id = Column(Integer, primary_key=True)
    nickname = Column(String(24), unique=True)
    _password = Column('password', String(100))

一般的玩法就是把对象属性给个都取出来,存放在字典里面,然后用jsonify序列化。这个玩多了,开发也差不多累了,心塞。因为这个方法不能直接序列化对象,那就想办法让它可以就牛逼了。
这里面有两个过程可以优化:1.对象快速转字典。2.对象嵌套快熟序列化

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
flask
Gupao