聆听风声 点点滴滴都很珍贵!

python使用flask返回json数据

2019-03-21

在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序列化。这个玩多了,开发也差不多累了,心塞。因为这个方法不能直接序列化对象,那就想办法让它可以就牛逼了。

这里面有两个过程可以优化:

  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

Similar Posts

Comments