3 个稳定版本
2.0.5 | 2022年7月17日 |
---|---|
2.0.4 | 2022年6月26日 |
2.0.3 | 2021年12月9日 |
392 在 编码 中排名
每月下载量 572
在 14 个 包(11 个直接)中使用
455KB
9K SLoC
bson
从 mongodb-bson 分支而来,并为 bson 添加了 u32/u64 类型支持
Rust 中 BSON 的编码和解码支持
索引
有用的链接
安装
需求
- Rust 1.48+
导入
该包在 crates.io 上可用。要在您的应用程序中使用它,只需将其添加到项目中的 Cargo.toml
文件中。
[dependencies]
rbson = "2.0"
注意,如果您正在通过 bson
包使用 mongodb
包,您不需要在 Cargo.toml
中指定它,因为 mongodb
包已经重新导出。
功能标志
功能 | 描述 | 额外依赖项 | 默认 |
---|---|---|---|
chrono-0_4 |
在公共 API 中启用对 chrono 包的 v0.4 版本的支持。 |
n/a | 否 |
uuid-0_8 |
在公共 API 中启用对 uuid 包的 v0.8 版本的支持。 |
n/a | 否 |
serde_with |
启用 serde_with 集成以支持 bson::DateTime 和 bson::Uuid |
serde_with | 否 |
BSON 格式概述
BSON,即二进制JSON,是类似于JSON的文档的二进制编码序列化形式。与JSON类似,BSON支持在文档和数组中嵌入文档和数组。BSON还包含扩展,允许表示JSON规范之外的类型。例如,BSON具有日期和时间类型以及二进制数据类型。
// JSON equivalent
{"hello": "world"}
// BSON encoding
\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是MongoDB的主要数据表示形式,并且该包在MongoDB的API和实现中用于mongodb
驱动程序包。
有关BSON本身的更多信息,请参阅bsonspec.org。
用法
BSON值
许多不同的类型可以作为BSON值表示,包括32位和64位有符号整数、64位浮点数、字符串、日期时间、嵌入的文档等。要查看可能的BSON值的完整列表,请参阅BSON规范。各种可能的BSON值通过该包中的Bson
枚举来建模。
创建Bson
实例
let string = Bson::String("hello world".to_string());
let int = Bson::Int32(5);
let array = Bson::Array(vec![Bson::Int32(5), Bson::Boolean(false)]);
let string: Bson = "hello world".into();
let int: Bson = 5i32.into();
let string = bson!("hello world");
let int = bson!(5);
let array = bson!([5, false]);
bson!
支持数组和对象字面量,并且它自动将指定的任何值转换为Bson
,前提是它们符合Into<Bson>
。
Bson
值解包
Bson
有一些辅助方法用于访问底层的Rust原生类型。在事先知道BSON值的特定类型的情况下,这些辅助方法可能很有用。
例如:
let value = Bson::Int32(5);
let int = value.as_i32(); // Some(5)
let bool = value.as_bool(); // None
let value = bson!([true]);
let array = value.as_array(); // Some(&Vec<Bson>)
BSON文档
BSON文档是有序的UTF-8编码字符串到BSON值的映射。在逻辑上类似于JSON对象,因为它们可以包含子文档、数组和几种不同类型的值。该包通过Document
结构来建模BSON文档。
创建Document
Document
可以直接从包含BSON数据的字节读取器创建,或者通过doc!
宏创建
let mut bytes = hex::decode("0C0000001069000100000000").unwrap();
let doc = Document::from_reader(&mut bytes.as_slice()).unwrap(); // { "i": 1 }
let doc = doc! {
"hello": "world",
"int": 5,
"subdoc": { "cat": true },
};
doc!
的工作方式与bson!
类似,不同之处在于它始终返回一个Document
而不是一个Bson
。
Document
成员访问
Document
有一些方法来简化成员访问
let doc = doc! {
"string": "string",
"bool": true,
"i32": 5,
"doc": { "x": true },
};
// attempt get values as untyped Bson
let none = doc.get("asdfadsf"); // None
let value = doc.get("string"); // Some(&Bson::String("string"))
// attempt to get values with explicit typing
let string = doc.get_str("string"); // Ok("string")
let subdoc = doc.get_document("doc"); // Some(Document({ "x": true }))
let error = doc.get_i64("i32"); // Err(...)
使用强类型数据结构建模 BSON
虽然可以直接处理文档和BSON值,但这通常会引入大量的样板代码,用于验证必要的键是否存在以及它们的值是否为正确的类型。《serde》库提供了一个强大的方式,可以自动将BSON数据映射到Rust数据结构,从而消除了所有这些样板代码的需求。
例如:
#[derive(Serialize, Deserialize)]
struct Person {
name: String,
age: i32,
phones: Vec<String>,
}
// Some BSON input data as a `Bson`.
let bson_data: Bson = bson!({
"name": "John Doe",
"age": 43,
"phones": [
"+44 1234567",
"+44 2345678"
]
});
// Deserialize the Person struct from the BSON data, automatically
// verifying that the necessary keys are present and that they are of
// the correct types.
let mut person: Person = bson::from_bson(bson_data).unwrap();
// Do things just like with any other Rust data structure.
println!("Redacting {}'s record.", person.name);
person.name = "REDACTED".to_string();
// Get a serialized version of the input data as a `Bson`.
let redacted_bson = bson::to_bson(&person).unwrap();
任何实现了《Serialize》和《Deserialize》接口的类型都可以以这种方式使用。这样做有助于将“业务逻辑”与将数据转换为/从其序列化形式转换的(反)序列化逻辑分离。这可以导致代码更加清晰、简洁,同时减少错误的可能性。
处理日期和时间
BSON格式包括一个日期时间类型,在这个crate中通过《DateTime》结构体来模拟,并为该结构体实现了《Serialize》和《Deserialize》接口,以便在序列化到或从BSON反序列化时产生和解析BSON日期时间。流行的crate《chrono》也提供了一个《DateTime》类型,但其《Serialize》和《Deserialize》接口在字符串上操作,因此当与BSON一起使用时,不会使用BSON日期时间类型。为了解决这个问题,可以启用《chrono-0_4》功能标志。此标志公开了一系列在《bson::DateTime》和《chrono::DateTime》之间的方便转换,包括用于将《chrono::DateTime》序列化和反序列化为BSON日期时间的《chrono_datetime_as_bson_datetime》serde辅助工具,以及为《Bson》实现的《From
例如:
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct Foo {
// serializes as a BSON datetime.
date_time: bson::DateTime,
// serializes as an RFC 3339 / ISO-8601 string.
chrono_datetime: chrono::DateTime<chrono::Utc>,
// serializes as a BSON datetime.
// this requires the "chrono-0_4" feature flag
#[serde(with = "bson::serde_helpers::chrono_datetime_as_bson_datetime")]
chrono_as_bson: chrono::DateTime<chrono::Utc>,
}
// this automatic conversion also requires the "chrono-0_4" feature flag
let query = doc! {
"created_at": chrono::Utc::now(),
};
处理 UUID
请参阅《bson::uuid`模块的模块级文档。
最低支持的Rust版本(MSRV)
此crate的MSRV目前为1.48.0。这很少会增加,如果确实增加,也只会发生在小版本或大版本发布中。
贡献
我们鼓励并乐于接受以GitHub拉取请求形式提交的贡献。在打开一个之前,请确保在本地运行测试;查看测试部分以获取有关如何执行此操作的信息。一旦您打开一个拉取请求,您的分支将与我们用于我们的持续集成系统的相同的测试矩阵运行,因此通常只需要在独立环境中对集成测试运行本地测试即可。记住,在打开拉取请求之前,始终运行linter测试。
运行测试
集成和单元测试
要实际运行测试,您可以使用《cargo`,就像在任何一个其他crate中一样
cargo test --verbose # runs against localhost:27017
Linter测试
我们的代码格式检查使用每晚构建版本的 rustfmt
来验证代码格式是否正确,并使用稳定版本的 clippy
进行静态错误检测。您可以使用 rustup
来安装它们。
rustup component add clippy --toolchain stable
rustup component add rustfmt --toolchain nightly
要运行代码格式检查,请在 .evergreen
目录下运行 check-clippy.sh
和 check-rustfmt.sh
脚本。
bash .evergreen/check-clippy.sh && bash .evergreen/check-rustfmt.sh
持续集成
对 master 分支的提交将自动在 evergreen 上运行。
依赖项
~3.5–5MB
~90K SLoC