英文原文:http://bsonspec.org/#/specification
1. 版本 1.0
BSON以二进制格式存储零个或多个键值对作为一个实体。我们称这个实体为“文档”。
下面所说的语法指的是1.0版本的BSON标准。我们使用伪BNF来写BSON语法。有效的BSON数据由非终结文档表示。
2. 基本类型
部分语法由以下基本类型作为终结符来构成。每种类型都必须序列化成低字节序格式。
byte 1个字节(8位)
int32 4个字节(32位有符号整数)
int64 8个字节(64位有符号整数)
double 8个字节(64位IEEE754浮点数)
3. 非终结符
接下来讲的是BSON语法的其他部分。注意,用引号括起来的字符串是终结符,并用C语言
语法来解释(例如,“\x01”表示二进制的0000 0001)。同时我们使用*操作符表示重复的次
数(例如,“\x01”*2即是“\x01\x01”)。当*操作符当成一元操作符来使用的话,表示重复
任意次。
document ::= int32 e_list "\x00" => BSON文档,其中int32表示整个文档的
总字节数
e_list ::= element e_list | "" =>元素序列
element ::= "\x01" e_name double =>浮点数
| "\x02" e_name string =>UTF-8字符串
| "\x03" e_name document =>内嵌文档
| "\x04" e_name document =>数组,数组是以整数作为键
值的普通BSON文档,并且键
值是从0开始依次递增。例如
数组["red","blue"]按文档来
编码后变成:
{'0':"red",'1':"blue"}。
| "\x05" e_name binary =>二进制数据
| "\x06" e_name =>未定义,不赞成使用
| "\x07" e_name =>ObjectId,12字节大小
| "\x08" e_name "\x00" =>布尔值“假”
| "\x08" e_name "\x01" =>布尔值“真”
| "\x09" e_name int64 =>UTC日期时间,其中int64
表示从1970年1月1日到
现在的毫秒数
| "\x0A" e_name =>空值
| "\x0B" e_name cstring cstring =>正则表达式,其中第一个cstring是
正则表达式,第二个cstring是正则的
选项,选项是用字母来表示,并安装字
母顺序来存储。有效选项有:'i'表示
匹配时不关心大小写,'m'表示多行
匹配,'x'表示详尽模式,'l'(小写的L)
表示\w,\W这些元字符依赖于语言环境,
's'表示'.'匹配任意字符,'u'表示
\w,\W这些元字符按照unicode来解释。
| "\x0C" e_name string =>数据库指针,12个字节大小,不赞成使用
| "\x0D" e_name string =>JavaScript 代码
| "\x0E" e_name string =>符号,类似于字符串,是语言所特有的
符号类型
| "\x0F" e_name code_w_s =>JavaScript code w/ scope
| "\x10" e_name int32 =>32位整数
| "\x11" e_name int64 =>时间戳,MongoDB复制和分片时使用的
特殊时间类型,前4个字节是增量,后4个
字节是时间戳。
| "\x12" e_name int64 =>64位整数
| "\xFF" e_name Min key =>最小键,比所有BSON元素值都小的
特殊类型
| "\x7F" e_name Max key =>最大键, 比所有BSON元素值都大的
特殊类型
e_name ::= cstring =>键名
string ::= int32 (byte*) "\x00" =>字符串,其中int32的值等于(byte*)的
字节数加1(算上尾部的“\x00”),而
(byte*)的值是UTF-8编码后的字符
cstring ::= (byte*) "\x00" =>CString,即若干个改进UTF-8编码字符,
并在尾部加上“\x00”。(byte*)不能
包含“\x00”,所以它并不是真正的
UTF-8编码的
binary ::= int32 subtype (byte*) =>二进制,其中int32表示(byte*)的
字节总数
subtype ::= "\x00" =>二进制或通用类型,这是最常用的子类型
| "\x01" =>函数
| "\x02" =>二进制(旧),是默认的子类型,
但是不赞成使用,建议使用“\x00”
子类型。驱动和工具必须正确处理
好“\x02”这个子类型。
| "\x03" =>UUID
| "\x05" =>MD5
| "\x80" =>用户自定义,二进制数据的结构是任意的
code_w_s ::= int32 string document =>Code w/ scope,其中int32表示整个
code_w_s值的字节长度,string是
JavaScript代码,document是
标识符到值的映射,代表string被评估的
范围
4.示例
下面是使用JavaScript或python风格的文档示例,以及相应的BSON表示。
{"hello": "world"} → "\x16\x00\x00\x00\x02hello\x00 \x06\x00\x00\x00world\x00\x00"
解释:\x16\x00\x00\x00表示文档的总长度为22字节,并且按低字节序存储的;
\x02hello\x00中的\x02表示键名是UTF-8字符串,hello是键名,\x00是键名的尾部填充;
\x06\x00\x00\x00world\x00中的\x06\x00\x00\x00表示world这个字符串的字节数加1,\x00是world字符串的尾部填充;
最后一个\x00是文档的尾部填充。
{"BSON": ["awesome", 5.05, 1986]} → "1\x00\x00\x00\x04BSON\x00&\x00
\x00\x00\x020\x00\x08\x00\x00
\x00awesome\x00\x011\x00333333
\x14@\x102\x00\xc2\x07\x00\x00\x00\x00"
PS:不好意思,这个例子我没看懂。
注:巴科斯范式(BNF: Backus-Naur Form 的缩写)是由 John Backus 和 Peter Naur 首先
引入的用来描述计算机语言语法的符号集。现在,几乎每一位新编程语言书籍的作者都使用巴科
斯范式来定义编程语言的语法规则。