3 个稳定版本

2.0.5 2022年7月17日
2.0.4 2022年6月26日
2.0.3 2021年12月9日

392编码 中排名

Download history 152/week @ 2024-03-12 185/week @ 2024-03-19 201/week @ 2024-03-26 215/week @ 2024-04-02 125/week @ 2024-04-09 172/week @ 2024-04-16 172/week @ 2024-04-23 159/week @ 2024-04-30 153/week @ 2024-05-07 174/week @ 2024-05-14 163/week @ 2024-05-21 186/week @ 2024-05-28 128/week @ 2024-06-04 100/week @ 2024-06-11 180/week @ 2024-06-18 133/week @ 2024-06-25

每月下载量 572
14 包(11 个直接)中使用

MIT 许可证

455KB
9K SLoC

bson

从 mongodb-bson 分支而来,并为 bson 添加了 u32/u64 类型支持

crates.io docs.rs crates.io

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::DateTimebson::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实例

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`接口,允许在《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`模块的模块级文档。

最低支持的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.shcheck-rustfmt.sh 脚本。

bash .evergreen/check-clippy.sh && bash .evergreen/check-rustfmt.sh

持续集成

对 master 分支的提交将自动在 evergreen 上运行。

依赖项

~3.5–5MB
~90K SLoC