BSON 二进制 JSON 格式
FreeGuideOnline
最新
2026-07-13
<total_document_length>...<null_byte_terminator>
- 前 4 字节(int32)表示整个文档的字节长度(包含该长度字段自身)。
- 之后是一系列连续的 BSON 元素。
- 以一个 `0x00` 字节作为文档结束标记。
每个 BSON 元素的结构为:
<type_byte><element_name>
- `type_byte`:1 字节的类型标识符,用于指定紧随其后的值是什么类型。
- `element_name`:以 `0x00` 结尾的 UTF-8 字符串(即 C-style 字符串),表示字段名。
- `value`:具体数据的二进制表示,其格式取决于类型。
对于嵌套文档和数组,它们作为特殊类型的值嵌入,内部同样遵循上述文档结构。
### BSON 支持的主要数据类型
BSON 定义了一套固定的类型代码,下表列出了常用的类型及其代码:
| 类型代码 | 类型名称 | 说明 |
|----------|-----------------|--------------------------------------|
| `\x01` | 64 位浮点数 | 对应 JSON 的 `number`,双精度 |
| `\x02` | UTF-8 字符串 | 长度前缀的 UTF-8 字符串 |
| `\x03` | 嵌入文档 | 嵌套的 BSON 文档 |
| `\x04` | 数组 | 嵌套的 BSON 文档,索引为字符串数字 |
| `\x05` | 二进制数据 | 包含子类型和长度的任意字节序列 |
| `\x06` | 未定义(已废弃) | 通常视作 null |
| `\x07` | ObjectId | 12 字节的唯一标识符 |
| `\x08` | 布尔值 | `\x00` 为 false,`\x01` 为 true |
| `\x09` | UTC 日期时间 | 64 位整数,自 UTC 纪元以来的毫秒数 |
| `\x0A` | Null 值 | 无值,仅类型码和键名 |
| `\x10` | 32 位整数 | 有符号 32 位整数 |
| `\x12` | 64 位整数 | 有符号 64 位整数 |
此外还有其他类型如 DBPointer、JavaScript 代码、正则表达式等,但上述为最常用类型。
### BSON 与 JSON 的对比
| 特性 | JSON | BSON |
|--------------|-------------------------------|---------------------------------|
| 格式 | 人类可读的文本 | 二进制格式,不易直接阅读 |
| 数据类型 | 字符串、数字、布尔、数组、对象、null | 额外支持日期、二进制、ObjectId、int32/64 等 |
| 解析速度 | 需将字符串解析为数据结构,较慢 | 直接根据长度和类型标签进行跳转式解析,极快 |
| 存储空间 | 紧凑,但字段名重复存储 | 字段名同样会重复存储,通常比 JSON 稍大(因为加入类型信息),但对于二进制数据更高效 |
| 适用场景 | 配置文件、API 响应、数据交换 | 数据库存储、内部 RPC、驱动与服务器的通信 |
| 可遍历性 | 必须线性扫描 | 可跳过不需要读取的部分 |
**重要误区澄清**:BSON 并不总比 JSON 体积小。对于纯文本数据,BSON 因为显式的类型字节和长度前缀,体积可能更大。其优势在于解析性能和二进制数据的高效处理。
### BSON 编码示例
假设有一个 JSON 文档:
```json
{
"name": "Alice",
"age": 30,
"active": true
}
简化的 BSON 编码结构(十六进制表示,忽略具体长度字段细节):
\x00 整个文档长度占位...
\x02 'name\x00' \x05\x00\x00\x00 'A' 'l' 'i' 'c' 'e' \x00 ← UTF-8 字符串,前导 4 字节长度
\x10 'age\x00' \x1E\x00\x00\x00 ← 32 位整数,小端序
\x08 'active\x00' \x01 ← 布尔值 true
\x00 ← 文档结束
数组的编码方式与文档相同,只是将索引(如 "0", "1", "2")作为字段名,并顺序排列。
为什么 MongoDB 选择 BSON?
- 快速遍历:当查询只需要返回文档中的部分字段时,MongoDB 存储引擎可以利用 BSON 的长度前缀直接跳过不相关的字段,显著减少 I/O 和解析开销。
- 丰富的数据类型:MongoDB 支持日期范围查询、地理位置索引、二进制大对象存储等,这些都需要底层格式支持特定的数据类型。
- 原位更新:如果文档中某个字段的值大小不变,MongoDB 可以直接在磁盘上覆盖该值而不需要重写整个文档,BSON 的固定长度类型(如 int32、int64、double)对此提供了基础支持。
- 高效编码/解码:驱动端可以快速将语言原生类型映射到 BSON,无需像 JSON 那样进行复杂的类型推断和字符串处理。
如何在编程中使用 BSON
通常你不会直接操作 BSON 二进制流,而是通过 MongoDB 驱动程序或 BSON 库进行处理。以 Node.js 为例:
const BSON = require('bson');
// 将 JS 对象序列化为 BSON 二进制
const doc = { name: 'Alice', age: 30 };
const bsonBytes = BSON.serialize(doc);
// 从 BSON 二进制反序列化回 JS 对象
const deserializedDoc = BSON.deserialize(bsonBytes);
console.log(deserializedDoc); // { name: 'Alice', age: 30 }