在Flask项目中使用Flask-SQLAlchemy操作数据库时,我们经常会需要把查询到的ORM对象返回给前端,这时候如果直接调用jsonify或者json.dumps方法,就会遇到Object of type User is not JSON serializable这类错误。这是因为Python原生的JSON序列化器只支持基础数据类型,无法处理自定义的ORM对象,接下来我们就逐一介绍可用的解决方案。

方案一:手动提取属性转字典
这是最基础的解决方式,直接把ORM对象的属性提取出来组成字典,再对字典进行JSON序列化,适合属性较少、结构简单的ORM对象。
from flask import Flask, jsonify
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(50))
age = db.Column(db.Integer)
@app.route('/user_manual')
def get_user_manual():
user = User.query.first()
# 手动提取属性组成字典
user_dict = {
'id': user.id,
'username': user.username,
'age': user.age
}
return jsonify(user_dict)方案二:自定义JSON编码器
如果项目中ORM对象较多,手动提取属性的方式会非常繁琐,这时候可以自定义Flask的JSON编码器,统一处理ORM对象的序列化逻辑。
from flask import Flask, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask.json import JSONEncoder
class CustomJSONEncoder(JSONEncoder):
def default(self, obj):
# 判断是否为Flask-SQLAlchemy的Model实例
if isinstance(obj, db.Model):
# 获取对象的所有列属性,排除私有属性
columns = [column.name for column in obj.__table__.columns]
result = {}
for column in columns:
value = getattr(obj, column)
result[column] = value
return result
# 其他类型交给父类处理
return super().default(obj)
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
app.json_encoder = CustomJSONEncoder
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(50))
age = db.Column(db.Integer)
@app.route('/user_encoder')
def get_user_encoder():
user = User.query.first()
# 现在可以直接传入ORM对象,编码器会自动处理
return jsonify(user)方案三:使用marshmallow库序列化
当ORM对象关系复杂、需要处理嵌套对象或者字段校验时,手动提取和自定义编码器的方式都不够灵活,这时候可以使用专业的序列化库marshmallow。
from flask import Flask, jsonify
from flask_sqlalchemy import SQLAlchemy
from marshmallow import Schema, fields
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(50))
age = db.Column(db.Integer)
# 定义User对应的序列化Schema
class UserSchema(Schema):
id = fields.Integer()
username = fields.String()
age = fields.Integer()
user_schema = UserSchema()
@app.route('/user_marshmallow')
def get_user_marshmallow():
user = User.query.first()
# 使用schema序列化对象,返回字典
user_data = user_schema.dump(user)
return jsonify(user_data)方案对比与选择建议
我们可以通过下面的表格对比三种方案的特点,根据实际场景选择:
| 方案 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 手动提取属性 | ORM对象属性少、结构简单,临时使用 | 实现简单,无额外依赖 | 重复工作多,对象属性变化时需同步修改代码 |
| 自定义JSON编码器 | 项目中ORM对象多,无复杂嵌套关系 | 一次配置全局生效,无需每个接口单独处理 | 对嵌套对象、特殊字段处理不够灵活 |
| marshmallow库 | 对象关系复杂、需要字段校验、多场景序列化 | 功能强大,支持嵌套、校验、自定义字段处理 | 需要额外安装依赖,配置稍复杂 |
在实际开发中,如果项目规模较小,手动提取属性或者自定义编码器就足够使用;如果是中大型项目,尤其是涉及复杂对象关系和接口校验的场景,更推荐使用marshmallow库,能够在长期维护中减少很多重复工作。
Flask-SQLAlchemyORM_serializationJSON_serializablePython_web修改时间:2026-05-28 21:43:13