You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用flask-jwt时遇到ObjectId类型对象无法JSON序列化的TypeError如何解决

问题原因

这个报错的核心是Python标准json库无法序列化MongoDB的ObjectId类型,Flask-JWT生成token时会默认序列化用户标识字段,你当前代码中用户主键是ObjectId类型,没有做序列化转换就直接参与json编码就会触发该错误。

解决方案

按以下步骤修改代码即可:

  1. 修正Customer类的to_json方法,将ObjectId转为字符串
# customer.py 中修改to_json方法
def to_json(self):
    return {
        "_id": str(self._id),
        "tel": self.tel,
        "password": self.password,
    }
  1. 为Flask应用配置自定义JSON编码器,全局支持ObjectId序列化
    在你的Flask应用初始化文件中添加如下代码:
import json
from bson import ObjectId

class CustomJSONEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, ObjectId):
            return str(obj)
        return super().default(obj)

# 替换你的app实例的json编码器
app.json_encoder = CustomJSONEncoder
  1. 调整JWT身份处理逻辑,兼容字符串格式的ObjectId查询
    首先自定义JWT身份提取回调,确保写入payload的用户ID是字符串类型:
# 放在JWT初始化后的位置
@jwt.jwt_identity_handler
def jwt_identity(user):
    return str(user._id)

然后修改service.py中的identity函数,将payload中读取的字符串ID转回ObjectId再查询:

# 先导入bson,修改identity方法
import bson
def identity(payload):
    _id = bson.ObjectId(payload['identity'])
    return find_by_id.get(_id)
  1. 可选优化(强烈建议修改)
    你当前代码中find_by_username和find_by_id是模块加载时一次性生成的全局字典,后续新增的用户无法被检索到,建议改为实时查询数据库:
# service.py 调整为动态查询
def auth(username, password):
    user = Customer.objects(tel=username).first()
    if user and safe_str_cmp(user.password.encode('utf-8'), password.encode('utf-8')):
        return user

def identity(payload):
    _id = bson.ObjectId(payload['identity'])
    return Customer.objects(_id=_id).first()

这样就不需要预加载所有用户数据,也避免了新用户无法登录的问题。

内容的提问来源于stack exchange,提问作者Amoungui Serge

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 07:18:02