BSON数据结构以及与JSON区别
BSON全名 Binay JSON,是一种能用来表示简单数据结构、关联数组的数据类型,目前主要被用于 MongoDB 数据库的数据存储和网络传输,来源于 JSON,可以理解为 JSON 格式的一种拓展
关于 BSON
BSON 全称 Binay JSON,意为二进制 JSON。
BSON 是一种能用来表示简单数据结构、关联数组的数据类型,目前主要被用于 MongoDB 数据库的数据存储和网络传输。
BSON 对象(文档)是由一个有序的元素列表组成,每个元素有字段名、类型、值组成。
BSON 名义上是 JSON 数据的超集,支持 date 和 字节数组,但是有个特殊的地方没有通用数字(number)类型。
BSON 主要着眼于提高扫描效率,因此对于大型元素提供长度字段作为前缀,包括显示数组索引等,因此想多而言占用的空间较 JSON 大。
数据类型
BSON 数据序列化格式支持如下格式:
- string
- integer(32 或 64 位)
- double(64 位 IEEE 754 浮点数)
- decimal128(128 位 IEEE 754-2008 浮点数;Binary Integer Decimal 变体),适合作为任意精度为 34 个十进制数字的数字载体,最大值近似 10
- date(整数,自 UNIX 时间的毫秒数)
- byte array(二进制数组)
- 布尔(true 或 false)
- null
- BSON 对象
- BSON 数组
- JavaScript 代码
- MD5 二进制数据
- 正则表达式(Perl 兼容的正则表达式,即 PCRE,版本 8.41,含 UTF-8 支持;与 Python 不完全兼容)
数据特点
- 轻量级:空间优势,虽然相对 JSON 较大,但是由于其脱胎于 JSON 还是有较大的空间优势。
- 可遍历性:每个元素的长度存在元素的头部,可以直接 seek 到指定的点上进行扫描读取,这一点主要体现在 MongoDB 中。(对比 JSON 而言,在遍历或扫描数据的时候,都需要全数据扫描)。
- 修改便捷:数据类型表示的存在,在空间上已经预留的相应的位置,在修改数据时一般不会出现整体位移的情况(除非调整了字段的数据类型),同比情况下 JSON 在修改数据时,后续的内容都需要随之前移或后移。
- 类型广泛:除了支持常见的数据类型,增加更多类型数据的支持。
- 高效性:使用 C 数据类型,因此在大多数语言中都可以将数据快速编码与解码。
数据实例
由于 BSON 是二进制格式的数据,仅仅通过文本形式我们无法感知到其与 JSON 格式的区别。
{
"name": "mebugs",
"size": 18,
"born": new Date("25/05/2005")
}
语法规范
官方语法规范:https://bsonspec.org/spec.html
基本类型
以下基本类型在语法的其余部分用作终结符。每种类型都必须以小端格式序列化。
| 类型 | 长度 | 描述 |
|---|---|---|
| byte | 1 byte | 8 位 |
| int32 | 4 bytes | 32 位有符号整数,二进制补码 |
| int64 | 8 bytes | 64 位有符号整数,二进制补码 |
| uint64 | 8 bytes | 64 位无符号整数 |
| double | 8 bytes | 64 位 IEEE754-2008 二进制浮点数 |
| decimal128 | 16 bytes | 128 位 IEEE754-2008 十进制浮点数 |
高级类型
BSON 语法的其余部分。
请注意,带引号的字符串表示终结符,应使用 C 语义进行解释。
例如"x01"表示 byte 0000 0001。
使用 * 运算符作为重复的简写(例如("x01"*2) is "x01x01")。
当用 * 作一元运算符时,意味着重复可以发生 0 次或多次。
| 类型 | 格式 | 描述 |
|---|---|---|
| document | int32 e_list "x00" | 文档=文档的长度(int32)+ 元素列表 +"x00" |
| document.e_list | element e_list | 元素列表=一个元素 + 元素列表 |
| element | "x01" e_name double | 元素类型:"x01"+ 元素名 +double |
| "x02" e_name string | 元素类型:"x02"+ 元素名 +string | |
| "x03" e_name document | 嵌入文档(子文档) | |
| "x04" e_name document | 数组 | |
| "x05" e_name binary | 二进制数据 | |
| "x06" e_name | 未定义的(值)-已弃用 | |
| "x07" e_name (byte*12) | 对象 ID,即 MongoDB 中默认的"_id"的类型。12 字节。 | |
| "x08" e_name "x00" | 布尔值 false | |
| "x08" e_name "x01" | 布尔值 true | |
| "x09" e_name int64 | UTC 日期时间 | |
| "x0A" e_name | 空值,如:null | |
| "x0B" e_name cstring cstring | 正则表达式 - 第一个 cstring 是正则表达式模式,第二个是正则表达式选项字符串。 | |
| "x0C" e_name string (byte*12) | DBPointer—已弃用 | |
| "x0D" e_name string | JavaScript 代码 | |
| "x0E" e_name string | 符号—已弃用 | |
| "x0F" e_name code_w_s | 带作用域的 JavaScript 代码—已弃用 | |
| "x10" e_name int32 | 32 位整数 | |
| "x11" e_name uint64 | 时间戳 | |
| "x12" e_name int64 | 64 位证书 | |
| "x13" e_name decimal128 | 128 位十进制浮点数 | |
| "xFF" e_name | 最小键 | |
| "x7F" e_name | 最大键 | |
| e_name | cstring | 元素名(键名) |
| string | int32 (byte*) "x00" | 字符串,长度 + 内容 +"x00" |
| cstring | (byte*) "x00" | 字符串,内容 +"x00" |
| binary | int32 subtype (byte*) | 二进制数据,长度 + 类型 + 内容 |
| subtype | "x00" | 二进制子类型,通用 |
| "x01" | 功能 | |
| "x02" | 二进制(旧) | |
| "x03" | UUID(旧) | |
| "x04" | UUID | |
| "x05" | MD5 | |
| "x06" | 加密的 BSON 值 | |
| "x80" | 用户定义 | |
| code_w_s | int32 string document | 带范围的代码 -已弃用 |
其他说明
- 数组:数组是一个普通的 BSON 文档,键是整数值,从 0 开始并按顺序继续。例如,数组 ['red', 'blue'] 将被编码为文档 {'0': 'red', '1': 'blue'}。键按数字升序排列。
- UTC 日期时间:实际值是 int64 类型,是自 Unix 纪元以来的 UTC 毫秒数。
- 时间戳:MongoDB 复制和分片使用的特殊内部类型。前 4 个字节是增量,后 4 个字节是时间戳。
- 最小键:较低于所有其他可能的 BSON 元素值的特殊类型。
- 最大键:比较高于所有其他可能的 BSON 元素值的特殊类型。
- 通用二进制子类型:常用的二进制子类型,应该是驱动程序和工具的“默认”。
- binary/BinData:用于表示字节数组。类似于 Java 中 ByteArray 的。二进制值有一个子类型,用于指示字节数组中的数据类型。0-127 是预定义或保留的。128-255 是用户定义的。
- x02 Binary (Old):曾是默认子类型,为了支持 x00 而被弃用。
- x03 UUID(旧):曾是 UUID 子类型,为了支持 x04 而被弃用。
- x80-xFF: “用户定义”子类型。二进制数据可以是任何东西。
数据样例
本示例来自网络,参考上方的规范表,会更加容易理解其存储方式。
