什么是BSON?什么是JSON?

JSON是什么?

JSON,JavaScript Object Notation,最初在2000年左右由JavaScript的设计者Douglas Crockford所定义。2003年才官方正式定名。

JavaScript中的对象类似于一个 关联容器 (比如Map,HashMap),每一个文本键都对应一个值(值的类型可以是数字、字符串、函数、或者另外一个对象)。这种简单的特性使得JavaScript的对象通过文本表达起来异常简单。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"_id": 1,
"name": {
"first": "John",
"last": "Backus"
},
"contribs": ["Fortran", "ALGOL", "Backus-Naur Form", "FP"],
"awards": [{
"award": "W.W. McDowell Award",
"year": 1967,
"by": "IEEE Computer Society"
}, {
"award": "Draper Prize",
"year": 1993,
"by": "National Academy of Engineering"
}]
}

随着JavaScript成为了web浏览器的默认 脚本语言 ,几乎所有的现代浏览器都支持JavaScript。JSON也有了更多的用武之地。由于这种格式兼顾了人的可读性和机器的可读性,并且其他语言实现起来也相对简单,JSON的使用范围大大超出原来的Web领域。比如:

  • API定义
  • 配置文件
  • 日志消息
  • 数据库存储

最常见的,比如 Restful API 就是基于HTTP协议的application/json的请求/响应,请求和响应都是JSON格式的。

MongoDB与JSON

MongoDB作为一款从一开始就被设计成为 现代应用 程序开发服务的数据存储平台。所以选择JSON这种通用格式作为MongoDB的文档模型是一件很自然的事情。但是JSON有几个问题:

  • JSON是文本格式的。 文本解析 通常比较慢。
  • JSON的存储格式 空间利用效率 比较低。
  • JSON只支持有限的集中基本数据类型。
    为了使得MongoDB以JSON作为文档模型,同时兼顾性能和通用目的,于是BSON应运而生: 用二进制来存储数据,同时针对性能、空间、灵活性做了专门的优化。

提示:从这个层面上来说,和protobuf、thrift并没有本质的差异。BSON可以作为一种通用的数据交换格式,类似于protobuf和thrift,或者avro之类的来使用。

BSON

BSON,Binary JSON,将JSON以 二进制 的方式存储。由于同时存储了字段的类型、长度,所以BSON的解析效率非常高。

同JSON一样,支持内嵌的文档对象和数组对象,但是BSON添加了一些JSON没有的一些数据类型,如Date和BinData类型。

BSON有三个特点:

  • 轻量性
    JSON采用文本格式存储,而BSON采用二进制。在空间占用上尽可能的小。

  • 可遍历性
    每个字段都会存储对应的key,每个对象都会存储对应的Schema。这使得对象可以完全的还原。这对MongoDB来说非常的关键。

  • 高效性
    由于使用了C语言的数据结构类型,使得BSON的数据编解码可以达到一个非常优秀的性能。

BSON还是JSON?

如何理解这两者之间的差异?从范式定义来说,两者是一样的,数据类型是一样的,表达方式也是一样的。

即便是BSON,如果不能以肉眼可以识别的方式表达出来,那可能也没有什么意义。

二者的区别是底层存储的差异。JSON的存储、传输都是文本;而MongoDB存储或者网络传输都是BSON。

但是,简化理解,你可以把MongoDB当做一款JSON数据库。所有可以通过JSON表示的数据都可以存储在MongoDB中,并按照JSON方式从数据库中取出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

{"hello": "world"} →

\x16\x00\x00\x00 // total document size

\x02 // 0x02 = type String

hello\x00 // field name

\x06\x00\x00\x00world\x00 // field value

\x00 // 0x00 = type EOO ('end of object')


{"BSON": ["awesome", 5.05, 1986]} →

\x31\x00\x00\x00

\x04BSON\x00

\x26\x00\x00\x00

\x02\x30\x00\x08\x00\x00\x00awesome\x00

\x01\x31\x00\x33\x33\x33\x33\x33\x33\x14\x40

\x10\x32\x00\xc2\x07\x00\x00

\x00

\x00

不同于某些系统直接将JSON存储为字符串,或者二进制的Blob,MongoDB通过BSON提供了强大的索引、查询能力。

比如 多层嵌套 的BSON/JSON文档,MongoDB允许开发者通过特定的键直接查询和操作这些对象,并生成索引。

不过在使用的时候,需要注意不同语言的抽象级别和具体的语法不同带来的不一致性,具体就需要参考对应的驱动的文档来详细的了解。比如

  • BSON可能包含原始JSON无法表达的对象(Date或者二进制)。
  • JSON对象的键是有序的。但是Python的字典是无须的,诸如此类的语义上的差异。
  • BSON支持一些列的数值类型。这些类型在JSON中不存在。并且不同的语言在对应这些数值类型的时候也不一样。

BSON有哪些实现?

由于MongoDB是第一个使用BSON的大型项目,所以很多实现实际上整合在了MongoDB的驱动中。几乎每一种语言都提供了BSON的实现库。这些库都可以 独立使用 。

库:

  • The MongoDB C++ Driver Library - MongoDB的官方C++驱动,健壮并经过了充分的测试。如果愿意,可以只使用其中BSON的部分。
  • gomongo - Driver for MongoDB.
  • bson - BSON serialization and deserialization library used by the official MongoDB Node.js driver.
  • PyMongo - official MongoDB driver
  • MongoDB Scala driver - Official MongoDB driver.

工具:

  • bsontools - Command line utilities for manipulating BSON files and for translating them to and from other formats such as CSV, JSON, and XML.
  • Kaitai Struct: BSON - Machine-readable description for generating a BSON parser automatically (C#, Java, JavaScript, Perl, PHP, Python, Ruby, …).

项目:

  • MongoDB - A distributed document-oriented database using BSON as both the network and on-disk representation of documents.
  • ModeShape - A hierarchical JCR data store using BSON to serialize the data.
  • bsonsearch - BSON matching engine to perform offline document comparisons without a MongoDB server. C dynamic library with Python wrapper.

BSON有哪些类型?

类型 编号 别名 注释
Double 1 “double”
String 2 “string”
Object 3 “object”
Array 4 “array”
Binary data 5 “binData”
Undefined 6 “undefined” Deprecated.
ObjectId 7 “objectId”
Boolean 8 “bool”
Date 9 “date”
Null 10 “null”
Regular Expression 11 “regex”
DBPointer 12 “dbPointer” Deprecated.
JavaScript 13 “javascript”
Symbol 14 “symbol” Deprecated.
JavaScript code with scope 15 “javascriptWithScope” Deprecated in MongoDB 4.4.
32-bit integer 16 “int”
Timestamp 17 “timestamp”
64-bit integer 18 “long”
Decimal128 19 “decimal” New in version 3.4.
Min key -1 “minKey”
Max key 127 “maxKey”

BSON vs JSON

BSON作为JSON数据的二进制表达,同时为了更为通用的应用做了特定的 扩展 ,对数据的存储和查询做了 优化 。总体来说,BSON就是JSON的亲兄弟。

类型 JSON BSON
Encoding 内置编码 UTF-8 String Binary
Data Support 类型支持 String, Boolean, Number, Array String, Boolean, Number (Integer, Float, Long, Decimal128…), Array, Date, Raw Binary
Readability 可阅读性 Human and Machine Machine Only

BSON和JSON的一个重要差异,就是BSON支持更多的 高级数据类型 。比如JavaScript的数值类型只定义了一个Number类型,没有从语言级别区分开整数和浮点数(浮点数也没有具体的精度控制)。大部分的后端开发语言都有复杂的数值类型,比如Java中有int, long, float, double,更高精度的有BigDecimal等等。所以这也是为什么BSON会做扩展的原因。扩展之后,很多复杂的数值计算都直接可以基于MongoDB提供的 算子 (Query Operator)或者 流水线 (Pipeline)来执行。

附上一张比较差异图:

总结

相比于传统的关系型数据库,采用BSON/JSON文档模型的数据库对开发者的一个最大的吸引力就是 动态 的、 灵活 的Schema。

首先,JSON文档是 Polymorphic ,也就是说同一个集合中不同的文档对象的字段可以不同。

其次,数据集合中的文档对象不需要提前声明Schema:文档是 自描述 的。开发人员可以直接开始写代码,并将对象存储到数据库中。

再次,如果要添加一个新的字段到文档中,直接添加即可,不会影响到集合中的其他文档,也不需要将数据库或者应用下线。对文档对象的变更也不需要修改集合的任何属性,不需要做ALTER TABLE之类的操作。

综合这些优势,文档模型提供的灵活性正好切合了现代程序开发过程中的这种诉求。

但是有的时候,灵活性是一个很强大的工具,但是在有一些场景下,你想对你的数据结构和内容有很多的控制。大部分的文档数据库都将这些 控制策略 交给开发者在 应用层 实施。但是,基本上大部分高级文档数据库都会提供Schema的校验机制,采用类似IETF JSON Schema标准类,比如MongoDB。

比如,如果使用Nodejs来开发后端服务的话,可以使用Mongoose ODM组件,提供了丰富的按照字段和数据类型进行校验的API,当然也可以自定义校验的规则。

下期预告

下一期推文中,我会将一些MongoDB比较适合的 应用场景 ,以及针对这些场景如何来建模,来抽离出一些通用的业务 建模原则 ,供大家阅读参考。

参考:

CSDN博客:https://blog.csdn.net/z69183787/article/details/26709505

JSON和BSON: https://www.mongodb.com/json-and-bson

JSON标准:https://json-schema.org/

BSON:https://bsonspec.org/

MongoDB数据类型:https://docs.mongodb.com/manual/reference/bson-types/