Sqlalchemy 能够很不便地做ORMapping,把数据库记录映射为业务实体类的实例,例如上面这样:
class Student(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(100)) city = db.Column(db.String(50)) addr = db.Column(db.String(200)) pin = db.Column(db.String(10))if __name__ == '__main__': student = Student.query.get(1)
但这种实例不不便序列化,比方要想在 Flask Web Service 接口中返回这个对象:
@app.route('/demo/db', methods=['GET'])def demo_db(): student = Student.query.get(1) return jsonify(student)
或者是间接转 JSON 字符串:
import jsonjson.dumps(student)
都会报错:Object of type Student is not JSON serializable
。
在网上搜的话,会有形形色色的答案,大部分都是让你实现某个相似 to_json 的办法,有些基本不论用,有些很麻烦。
其实最简略的解决方案就是:
用 python 3.7 引入的 dataclass
装璜器,这个装璜器帮咱们实现了对应的办法,能够间接把类变量申明当做实例变量的定义:
from dataclasses import dataclass@dataclassclass Student(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(100)) city = db.Column(db.String(50)) addr = db.Column(db.String(200)) pin = db.Column(db.String(10))
这时候,再调用 jsonify(student)
就不会报错了,但奇怪的是,后果是个空对象:{}
。
原来 dataclass 装璜器“认可”的字段申明,必须有 type annotation,改成上面这样:
from dataclasses import dataclass@dataclassclass Student(db.Model): id: int = db.Column(db.Integer, primary_key=True) name: str = db.Column(db.String(100)) city: str = db.Column(db.String(50)) addr: str = db.Column(db.String(200)) pin: str = db.Column(db.String(10))
输入后果就完满了:
{ addr: "xxx", city: "bj", id: 1, name: "hui", pin: "xyz"}
不过jsonify
尽管可用了,json.dumps
仍然会报错,最简略的方法,是先把对象转为 dict,再转 json:
import jsonfrom dataclasses import dataclassprint(json.dumps(dataclasses.asdict(student)))