Python+Flask+Marshmallow开发API遇<Object id>无法JSON序列化问题
解决Flask+Marshmallow中SQLAlchemy对象无法JSON序列化的问题
我一眼就看出你碰到的是SQLAlchemy模型实例直接返回时的序列化坑——当你尝试把User模型对象直接丢给jsonify()或者返回给客户端时,Flask自带的JSON编码器根本不知道怎么处理这些带着数据库连接属性的对象,直接就抛出<Object id> is not JSON serializable错误了。
结合你现有的代码,给你一步步的解决方案:
1. 先把User模型补全
看你代码里sta...应该是没写完的状态字段?先把模型定义完整,比如:
class User(db.Model): userid = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(30)) badgenum = db.Column(db.String(30)) mail = db.Column(db.String(30)) status = db.Column(db.String(10), default='active') # 可根据实际需求调整 created_at = db.Column(db.DateTime, default=datetime.datetime.utcnow)
2. 给User模型配个Marshmallow Schema
Marshmallow就是专门干序列化这事儿的,能把SQLAlchemy对象转成JSON能识别的纯字典结构。你可以选自动生成或手动定义两种方式:
自动生成Schema(推荐,省事儿)
class UserSchema(ma.SQLAlchemyAutoSchema): class Meta: model = User # 指定对应的SQLAlchemy模型 load_instance = True # 允许从字典反向生成模型实例,后续做POST/PUT请求时有用 include_fk = False # 不需要外键的话设为False # 初始化schema实例:单个用户用user_schema,多个用户列表用users_schema user_schema = UserSchema() users_schema = UserSchema(many=True)
手动定义Schema(适合需要自定义字段的场景)
class UserSchema(ma.Schema): userid = fields.Integer() name = fields.String() badgenum = fields.String() mail = fields.String() status = fields.String() created_at = fields.DateTime()
3. 在视图函数里用Schema序列化对象
你之前肯定是直接返回了模型实例,比如这样:
@app.route('/users/<int:user_id>', methods=['GET']) def get_user(user_id): user = User.query.get(user_id) return jsonify(user) # 这里直接传模型对象必报错!
正确的姿势是先用Marshmallow的dump()方法把对象转成纯字典,再传给jsonify():
@app.route('/users/<int:user_id>', methods=['GET']) def get_user(user_id): user = User.query.get_or_404(user_id) # 用get_or_404更友好,找不到直接返回404 # 用schema把模型对象序列化成字典 serialized_user = user_schema.dump(user) return jsonify(serialized_user) # 如果是返回用户列表 @app.route('/users', methods=['GET']) def get_users(): all_users = User.query.all() serialized_users = users_schema.dump(all_users) return jsonify(serialized_users)
4. 额外优化:处理DateTime字段的格式(可选)
如果你的模型里有DateTime字段,默认序列化后是ISO格式字符串,要是你想改成更友好的格式(比如YYYY-MM-DD HH:MM:SS),可以在Schema里指定:
class UserSchema(ma.SQLAlchemyAutoSchema): # 自定义DateTime字段的格式化 created_at = fields.DateTime(format='%Y-%m-%d %H:%M:%S') class Meta: model = User load_instance = True
最后说下为啥会报错
SQLAlchemy的模型实例不是普通的Python字典,它内部藏着数据库会话、延迟加载这些额外属性,Flask默认的JSON编码器只能处理字符串、数字、列表、字典这些基础类型,根本搞不定这些带数据库属性的对象。所以必须通过Marshmallow把对象转换成纯字典结构,才能被JSON正常序列化。
内容的提问来源于stack exchange,提问作者JeanSec
相关产品推荐
相关产品推荐

