BSON 解析

把 MongoDB 的二进制文档还原成可读字段,ObjectId、日期、Long、Decimal128 都按 Extended JSON 保留类型。

十六进制可以带空格、逗号或 0x 前缀,Base64 的换行会忽略。示例是 { hello: "world" }。

怎么读这个结果

BSON 的每个文档以 4 字节小端长度开头,长度包含自身和结尾的 0x00。后面是「类型字节 + cstring 字段名 + 值」,数组其实是键为 0、1 的文档。嵌入文档也是完整的一段,所以能递归还原。

ObjectId 有 12 字节,前 4 字节是创建时间戳;日期是 8 字节有符号毫秒数;Long 是 8 字节整数;Decimal128 是 128 位十进制浮点,专门给金额这类不能丢精度的场景。这些在 JSON 里分别用 $oid、$date、$numberLong、$numberDecimal 表示。

规范模式(canonical)保留所有类型信息,适合排查「为什么这个字段是字符串不是数字」。宽松模式(relaxed)把人能读的值直接展开,适合快速看内容;注意 Long 超出安全整数时会退化成 $numberLong,这是故意的。

要看其他二进制格式,用Protobuf 解码、MessagePack 编解码 或CBOR 编解码;只想按字节查看,用十六进制查看器。

常见问题

这段数据要从哪里复制?

mongosh 里可以用 EJSON.stringify(doc, { relaxed: false }) 看文本;二进制一般来自 mongodump 的 .bson 文件、驱动里的 raw 响应,或者抓包。把字节转成十六进制后贴进来即可,页面只处理粘贴进来的文本。

为什么输出里都是 $oid、$date?

JSON 没有 ObjectId 和日期类型,MongoDB 定义了 Extended JSON 来保留类型信息。规范模式会写成 $numberInt、$numberLong 这样的形式,宽松模式尽量还原成普通数字和字符串。排查类型问题时看规范模式。

一个 BSON 文件里有多个文档怎么办?

BSON 文档自带 4 字节小端长度,拼接在一起也能逐个切开。工具会按长度循环解析,最多处理 500 个文档;遇到长度对不上会停在出错的位置并给出偏移。

Decimal128 会丢精度吗?

解码用的是 bson 官方的 Decimal128 实现,值本身不会丢。真正容易出问题的是把 Decimal128 转成 JavaScript number 再参与运算,超过 2^53 就会失真,所以输出保持十进制字符串。

解析到一半报长度不对?

最常见的是复制时截断了,或者把 Base64 当十六进制贴了。十六进制里出现 g-z 以外的字符、长度为奇数,也会在解析前就被拦下来。先确认字节数和文档头声明的长度一致。

能直接编辑后再转回 BSON 吗?

这个页面只做解析。要生成 BSON 可以用 MongoDB 驱动或 EJSON.parse 后再 BSON.serialize;注意 Extended JSON 的类型标记要保留,否则日期会变成字符串、Long 会变成 double。