2、flask序列化
...About 2 min
2、flask序列化
一、为什么需要序列化
- 序列化常见的使用场景是web,比如一个接口需要返回一个对象,这个对象不可以被
flask的jsonify函数所序列化
@api.route('', methods=["GET"])
@auth.login_required
def get_user():
uid = g.user.uid
user = User.query.filter_by(id=uid).first_or_404_for_api()
return jsonify(user)
二、问题为什么对象不可以直接被序列化
2.1、可以被json直接序列化的为dict类型,python对象如何转为dict?
类中需要有两个方法keys, __getitem__
class Person(object):
name = "blue"
age = 18
def __init__(self, gender):
self.gender = gender
def keys(self):
return ("name", "age", "gender")
def __getitem__(self, item):
return getattr(self, item)
测试结果
person = Person("name")
print(dict(person))
# {'name': 'blue', 'age': 18, 'gender': '男'}
dict方法可以自定义字典的key, 它是读取class中的keys方法的返回值,作为字典的key
class Person(object):
name = "blue"
age = 18
def __init__(self, gender):
self.gender = gender
def keys(self):
return ("name", "age")
def __getitem__(self, item):
return getattr(self, item)
person = Person("name")
print(dict(person))
# {'name': 'blue', 'age': 18}
2.2、对象的__dict__有什么用?
class的__dict__方法是可以将对象中的实例属性返回,不返回类的类属性
class Person(object):
name = "blue"
age = 18
def __init__(self, gender):
self.gender = gender
def keys(self):
return ("name", "age", "gender")
def __getitem__(self, item):
return getattr(self, item)
person = Person("男")
print(person.__dict__) # {'gender': '男'}
三、自定义flask的序列化
一、指定flask的JSONEncoder,重写JSONEncoder的default方法
# !/usr/bin/env python
# -*-coding:utf-8 -*-
"""
# File : __init__.py.py
# Time :2022-05-03 10:42
# Author :author name
# version :python 3.7-32bit
# Description:
"""
import dataclasses
import decimal
import typing as t
import uuid
from datetime import date
from flask import Flask as _Flask
from flask.json import JSONEncoder as _JSONEncoder
from werkzeug.http import http_date
from app.libs.api_exceptions.api_exception import APIException
class JSONEncoder(_JSONEncoder):
def default(self, o: t.Any) -> t.Any:
if isinstance(o, date):
return http_date(o)
if isinstance(o, (decimal.Decimal, uuid.UUID)):
return str(o)
if dataclasses and dataclasses.is_dataclass(o):
return dataclasses.asdict(o)
if hasattr(o, "__html__"):
return str(o.__html__())
if hasattr(o, 'keys') and hasattr(o, '__getitem__'):
return dict(o)
raise APIException("serialize error")
# 后续使用这个Flask进行实例化
class Flask(_Flask):
json_encoder = JSONEncoder
二、修改模型类
模型类中必须要有这两个方法keys, __getitem__,__getitem__方法可以写在Base类中
class User(Base):
id = Column(Integer, primary_key=True)
email = Column(String(24), unique=True, nullable=False)
nickname = Column(String(24), unique=True)
auth = Column(SmallInteger, default=1)
_password = Column('password', String(128))
def keys(self):
return ["id", "email", "nickname", "auth"]
def __getitem__(self, key):
return getattr(self, key)
Powered by Waline v2.15.8