JSON.parse 无法直接解析 BSON,需通过 Extended JSON 序列化后配合 reviver 函数还原 ObjectId、Date 等类型,并辅以运行时校验确保安全性与准确性。

JSON.parse 本身不支持直接解析 BSON 数据,也不能处理“不规则结构”——它只接受合法的 JSON 字符串。BSON 是 MongoDB 的二进制格式,和 JSON 有本质区别(比如支持 ObjectId、Date、Binary、Decimal128 等非 JSON 原生类型)。所以问题核心不是“JSON.parse 的高级特性”,而是:如何把 BSON 序列化后的数据(通常是服务端转成字符串传给前端)安全、准确地映射为前端可用的标准 JavaScript 对象。
明确 BSON 到前端模型的转换边界
BSON 无法在浏览器中原生解析。实际流程通常是:
- 后端(如 Node.js + mongodb driver)将 BSON 文档用 mongodb Extended JSON v2 格式序列化(例如
{"$oid": "60a1b2c3d4e5f67890123456"}或{"$date": "2021-05-15T12:34:56.789Z"}) - 这个字符串是合法 JSON,可被
JSON.parse正常读取 - 但解析后得到的是带类型标记的对象(如
{ $oid: '...' }),还不是前端需要的 Date / ObjectId 实例等
用 reviver 函数做类型还原(JSON.parse 最实用的“高级特性”)
JSON.parse(text, reviver) 的 reviver 参数可在解析过程中逐字段干预,是实现类型还原的关键:
- 识别
$oid字段 → 构造ObjectId实例(需前端引入mongodb ObjectId类) - 识别
$date→ 转为Date对象 - 识别
$regex/$options→ 构建RegExp - 识别
$decimal128→ 使用Decimal128类(或转为字符串/Number,视精度要求而定)
示例 reviver:
前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。
立即学习“Java免费学习笔记(深入)”;
function bsonReviver(key, value) {
if (value != null && typeof value === 'object') {
if (Object.keys(value).length === 1 && '$oid' in value) {
return new ObjectId(value.$oid);
}
if ('$date' in value) {
return new Date(value.$date);
}
if ('$regex' in value && '$options' in value) {
return new RegExp(value.$regex, value.$options);
}
if ('$decimal128' in value) {
return Decimal128.fromString(value.$decimal128.$numberDecimal);
}
}
return value;
}
const raw = '{"_id":{"$oid":"60a1b2c3d4e5f67890123456"},"createdAt":{"$date":"2021-05-15T12:34:56.789Z"}}';
const model = JSON.parse(raw, bsonReviver); // {_id: ObjectId(...), createdAt: Date(...)}
配合 TypeScript 接口做运行时类型校验
reviver 解析后仍是普通对象,建议结合类型守卫或简单校验提升健壮性:
- 检查
_id是否为instanceof ObjectId - 验证
createdAt是有效Date(!isNaN(date.getTime())) - 对必填字段做存在性判断(避免后端漏传导致前端崩溃)
- 可封装为
parseBsonModel<T>(json: string, reviver?: Reviver): T泛型函数
避免踩坑:不推荐的“捷径”
- ❌ 直接
eval()或Function()执行 BSON 字符串(极不安全) - ❌ 用正则全局替换
"$oid"再 parse(易误伤字段名或字符串值) - ❌ 假设所有日期都是
$date,忽略$timestamp或毫秒数格式 - ❌ 在 reviver 中修改原始 value 引用(应返回新值,保持不可变)
真正可靠的方案,是服务端统一输出 Extended JSON,前端用 reviver 还原,再叠加轻量校验。不复杂但容易忽略。

















