Flask中自定义JSONEncoder

正在用Flask写个小项目,要实现将自定义类型转化成json格式。Flask一般用jsonify来使接口返回json数据,实现一个Flask内使用的JSONEncoder。

from flask.json import JSONEncoder

#编写自己的json编码器,并继承原有的
class MyJSONEncoder(JSONEncoder):
    #在jsonify中不能直接序列化该类型的时候,才会调用default方法,并进入分类执行
    def default(self, obj):
        if isinstance(obj, EqltByGene):
            #自定义返回字典
            return {
                'gene_id': obj.gene_id, 
                'gene_symbol': obj.gene_symbol,
                'p_value': obj.p_value,
            }
        return super(MyJSONEncoder, self).default(obj)

app = Flask(__name__)
app.json_encoder = MyJSONEncoder #将自定义的json编码器赋给flask原有的

这样在使用jsonify的时候,就可以将MyObject类型的实例转化到json格式。

问题思考:

  1. 如果项目中有很多自定义Class,都有这个需求,JSONEncoder的实现似乎会很丑陋,有什么好的方式?
  2. 同一个Class在不同的场景,json后要保留的字段差别如果很大,该如果实现?

对该问题的实现,可以采用以下方式:

#在模型对象中重写dict方法
class User(Base):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(50), unique=True, nullable=False)
    nickname = db.Column(db.String(24), unique=True)
    auth = db.Column(db.SmallInteger, default=1) # 1是普通用户,2是管理员
    _password = db.Column('password', db.String(100))

    #自定义将模型对象转成dict ,即dict(user)
    #dict(user),会先调用keys方法,这里重写,自定义获取返回的字段
    def keys(self):
        return ['id', 'email', 'nickname', 'auth']

    # dict(user)获取完字段后,会取出对应字段的值,这里使用__getitem__,这里getattr(self, item)拿到值信息,item为key名
    def __getitem__(self, item):
        return getattr(self, item)

以上的keys和getitem方法,会在自定义的jsonencoder方法中dict(对象)时候调用,如下:

#自定义json方法,在方法中实现对象转字典返回,这需要在模型对象中实现对应dict方法
class JSONEncoder(_JSONEncoder):
    def default(self, o):
        return dict(o)

调用方法如:

def get_user(uid):
    user = User.query.get_or_404(uid)
    return jsonify(user)

所以这样就实现了jsonencoder将对象转化成字典,然后直接jsonnfy调用序列化。并且复用性强,在模型中定义dict调用的方法,使得转化的字典key可以控制。

Last modification:November 26th, 2019 at 09:59 am
如果觉得我的文章对你有用,请随意赞赏

Leave a Comment