64个版本 (22个稳定版)
2.11.0 | 2024年6月5日 |
---|---|
2.9.0 | 2024年1月25日 |
2.8.1 | 2023年12月12日 |
2.7.0 | 2023年8月30日 |
0.1.2 | 2015年6月24日 |
#20 in 编码
每月下载量179,104
用于 417 个crate(直接使用206个)
625KB
14K SLoC
bson
Rust中BSON的编码和解码支持
索引
有用链接
安装
要求
- Rust 1.48+
导入
此crate可在crates.io上使用。要在您的项目中使用它,只需将其添加到项目的Cargo.toml
文件中。
[dependencies]
bson = "2.11.0"
请注意,如果您正在通过mongodb
crate使用bson
,则无需在您的Cargo.toml
文件中指定它,因为mongodb
crate已经重新导出了它。
特性标志
特性 | 描述 | 额外依赖项 | 默认 |
---|---|---|---|
chrono-0_4 |
在公共API中启用对chrono crate的v0.4版本的支持。 |
n/a | 无 |
uuid-0_8 |
在公共API中启用对uuid crate的v0.8版本的支持。 |
n/a | 无 |
uuid-1 |
在公共API中启用对 uuid 集合 v1.x 的支持。 |
n/a | 无 |
serde_with |
启用 serde_with 1.x 集成以支持 bson::DateTime 和 bson::Uuid 。 |
serde_with | 无 |
serde_with-3 |
启用 serde_with 3.x 集成以支持 bson::DateTime 和 bson::Uuid 。 |
serde_with | 无 |
BSON 格式概述
BSON,即 Binary JSON,是类似 JSON 文档的二进制编码序列化格式。和BSON一样,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 的 mongodb
驱动程序集合的 API 和实现中使用。
有关 BSON 的更多信息,请参阅 bsonspec.org。
用法
BSON 值
许多不同的类型都可以表示为 BSON 值,包括 32 位和 64 位有符号整数,64 位浮点数,字符串,日期时间,内嵌文档等等。要查看可能的 BSON 值的完整列表,请参阅 BSON 规范。该集合通过 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格式包括一个日期时间类型,该类型在本软件包中由 bson::DateTime
结构体建模,该结构体的 Serialize
和 Deserialize
实现将BSON日期时间在序列化到或从BSON反序列化时生成和解析。流行的软件包 chrono
也提供了一个 DateTime
类型,但其 Serialize
和 Deserialize
实现在字符串上操作,因此在使用BSON时,不使用BSON日期时间类型。为了解决这个问题,可以启用 chrono-0_4
功能标志。此标志公开了多个在 bson::DateTime
和 chrono::DateTime
之间的便捷转换,包括 chrono_datetime_as_bson_datetime
serde 辅助函数,该函数可以用于将 chrono::DateTime
序列化/反序列化为BSON日期时间,以及 Bson
的 From<chrono::DateTime>
实现对于允许在 doc!
和 bson!
宏中使用 chrono::DateTime
值。
例如:
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
模块 的模块级文档。
WASM支持
此软件包编译为 wasm32-unknown-unknown
目标;在这样做时,使用 js-sys
软件包为 ObjectId
生成中的当前时间戳组件。
最低支持的Rust版本(MSRV)
此软件包的MSRV目前是1.64.0。这很少会增加,并且如果确实增加,也只会在小版本或大版本发布时发生。
贡献
我们鼓励并乐意接受以GitHub拉取请求形式提交的贡献。在提交之前,请务必在本地运行测试;查看测试部分了解如何进行。一旦你打开一个拉取请求,你的分支将与我们用于持续集成系统的相同测试矩阵进行运行,因此通常只需在独立环境中本地运行集成测试即可。记得在提交拉取请求之前始终运行代码格式化测试。
运行测试
集成和单元测试
要实际运行测试,你可以像在其他crate中一样使用cargo
cargo test --verbose # runs against localhost:27017
代码格式化测试
我们的代码格式化测试使用rustfmt
的nightly版本来验证源代码格式是否正确,并使用稳定版本的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
持续集成
对main的提交将在evergreen上自动运行。
依赖关系
~4.5–6.5MB
~122K SLoC