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

如何将MongoDB ObjectId追加到Python类对象并完成序列化?

问题:MongoDB ObjectId列表序列化Python类对象失败

我尝试将从MongoDB查询得到的ObjectId列表result1添加到自定义的Transaction类对象中,使用json_util序列化但未成功,运行代码时抛出TypeError。

原代码

import json
import pyodbc
import pandas as pd
import os
from bson import json_util
from pymongo import MongoClient

class Medicine:
    def __init__(self, sku, name, diagnosis):
        self.sku = sku        
        self.name = name        
        self.diagnosis = diagnosis    
        
    def jsonable(self):
        return self.__dict__

class Transaction:
    def __init__(self, custId, bill_no, parent_tx_id, med):
        self.custId = custId        
        self.bill_no = bill_no        
        self.parent_txxxx_id = parent_tx_id        
        self.med = med    
    
    def jsonable(self):
        return self.__dict__

class Diagnosis:
    def __init__(self, name):
        self.name = name    

    def jsonable(self):
        return self.__dict__
        
def ComplexHandler(Obj):
    if hasattr(Obj, 'jsonable'):
        return Obj.jsonable()
    else:
        raise TypeError

client = MongoClient("mongodb+srv://root:xyz@abcmongodb.net/?retryWrites=true&w=majority")
# Select the database and collection
db = client["test"]
collection = db["collection1"]

# Run the query and extract the _id values from the documents
result1 = [doc["_id"] for doc in collection.find({}, {"_id": 1})]

# Print the results
print(result1) #Sample Output: [ObjectId('6409b51df917b0440431c0ba'), ObjectId('6409b51df917b0440431c0bb')]
    
diag = Diagnosis("CBT")
med = Medicine("SKU01", "Dolo", diag)
transaction = Transaction("adsf", "bu_bill", result1, med)
jsonTran = json.dumps(transaction, default=ComplexHandler)
print(jsonTran)

报错信息

File "x.py", line 55, in <module>
 jsonTran = json.dumps(transaction, default=ComplexHandler)  
File "/usr/lib/python3.8/json/__init__.py", line 234, in dumps     
 return cls(   
File "/usr/lib/python3.8/json/encoder.py", line 199, in encode   
  chunks = self.iterencode(o, _one_shot=True)   
File "/usr/lib/python3.8/json/encoder.py", line 257, in iterencode             
  return _iterencode(o, 0)   
File "x.py", line 39, in ComplexHandler
 raise TypeError TypeError

预期输出

{"custId": "adsf", "bill_no": "123", "parent_txxxx_id": [ObjectId('6409b51df917b0440431c0ba'), ObjectId('6409b51df917b0440431c0bb')], "med": {"sku": "SKU01", "name": "Dolo", "diagnosis": {"name": "CBT"}}}

解决方案

错误原因

自定义的ComplexHandler仅处理了带有jsonable方法的自定义类对象,但MongoDB的ObjectId并没有这个方法。当序列化Transaction对象的parent_txxxx_id字段(即ObjectId列表)时,列表中的每个ObjectId都会触发ComplexHandler抛出TypeError。

解决方法一:扩展ComplexHandler处理ObjectId

修改ComplexHandler,加入对ObjectId的判断,使用json_util或直接转字符串来序列化:

from bson import ObjectId, json_util

def ComplexHandler(Obj):
    if hasattr(Obj, 'jsonable'):
        return Obj.jsonable()
    elif isinstance(Obj, ObjectId):
        # 若要保留MongoDB标准的ObjectId JSON格式,用以下代码
        return json_util.loads(json_util.dumps(Obj))
        # 若仅需要纯字符串ID,替换为 return str(Obj)
    else:
        raise TypeError

解决方法二:直接用json_util序列化字典

利用自定义类的jsonable方法先将对象转成字典,再用json_util.dumps序列化(json_util原生支持ObjectId处理):

# 替换原有的json.dumps代码
tran_dict = transaction.jsonable()
jsonTran = json_util.dumps(tran_dict)
print(jsonTran)

这种方法更简洁,无需修改ComplexHandler,直接借助json_util对MongoDB类型的原生支持完成序列化。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 21:24:53