pymongo查询结果含objectid等bson类型,原生json.dumps()不支持,需用bson.json_util.dumps()序列化为mongodb extended json格式,保留类型信息且可逆。

PyMongo 查询返回的不是 JSON,而是 dict、list 等原生 Python 对象,其中还混着 ObjectId、datetime、Decimal128 等 BSON 类型 —— 这些类型 Python 的 json.dumps() 默认不认识,直接序列化会报 TypeError: Object of type ObjectId is not JSON serializable。
所以“不规范”不是 JSON 格式错,是 **Python 原生 JSON 库无法处理 BSON 扩展类型**。解决路径很明确:不用 json.dumps(),改用 bson.json_util 提供的专用序列化工具。
为什么不能直接用 json.dumps() 处理 PyMongo 查询结果
PyMongo 从 MongoDB 读出的数据保留了 BSON 类型语义,例如:
-
ObjectId("60a8b1c2d3e4f5a6b7c8d9e0")不是字符串,是bson.ObjectId实例 -
ISODate("2026-05-12T10:30:00Z")在 Python 中是datetime.datetime,但带有时区信息或毫秒精度,可能触发json的默认行为异常 -
BinData、DBRef、MaxKey等类型全都不在json.JSONEncoder的默认支持列表里
强行用 json.dumps() 就像拿菜刀切钢板——不是格式问题,是工具不对。
bson.json_util.dumps() 能做什么
它专为 BSON → JSON 场景设计,把非标准类型转成带类型标记的 JSON 对象(类似 MongoDB Shell 的输出格式),例如:
{"_id": {"$oid": "60a8b1c2d3e4f5a6b7c8d9e0"}, "created_at": {"$date": {"$numberLong": "1747045800000"}}}
这种格式虽然“看起来不干净”,但可逆、无损、标准兼容,前端或后续解析器只要按 MongoDB Extended JSON 规范处理即可还原。
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
使用方式很简单:
- 导入:
from bson.json_util import dumps - 序列化:
dumps(doc)或dumps(list_of_docs) - 注意:
dumps()返回的是字符串,不是字节;若需写文件,直接write()即可
如果只想输出“人眼友好”的纯 JSON(丢弃类型信息)
可以先用 bson.json_util.loads(dumps(doc)) 反序列化一次,再用 json.dumps() 输出 —— 但这会丢失 ObjectId 等类型,变成普通字符串,且 datetime 变成 ISO 格式字符串(如 "2026-05-12T10:30:00Z")。更稳妥的做法是自定义 JSONEncoder:
- 继承
json.JSONEncoder - 重写
default()方法,对ObjectId返回str(obj),对datetime返回obj.isoformat() - 调用时传入
cls=YourEncoder
但要注意:这种“降级”不可逆,ObjectId 字符串无法再还原为对象,除非你额外加字段标记类型。
容易被忽略的关键点
很多人试了 bson.json_util.dumps() 后发现返回的 JSON 里多了 $oid、$date,以为“修错了”。其实这恰恰是对的 —— 它不是 bug,是 BSON 类型保真机制。如果你的下游系统(比如前端框架、另一个服务)没按 Extended JSON 规范解析,那问题不在序列化端,而在消费端缺少对应解码逻辑。










