Overview
In this guide, you can learn about how the Rust driver handles conversions between BSON and Rust types. The process of converting a Rust type to BSON is called serialization, while the reverse process is called deserialization.
The Rust language uses a static type system, but BSON has a dynamic schema. To handle conversions between Rust types and BSON, the driver and the bson crate integrate functionality from the Serde framework.
Tip
The bson
crate is exported with the mongodb
crate. To learn how
to install the serde
crate, see serde
at the crates.io
crate registry.
By implementing functionality from the serde
crate into your
application, you can use custom Rust types such as structs and enums
to model your data.
This guide includes the following sections:
Generic Type Parameter describes collection parameterization and data modeling
Custom Data Model describes how to define custom Rust types to model data in your collections
Custom Serialization describes how to modify default serialization and deserialization behavior by using attributes and provides examples
Additional Information provides links to resources and API documentation for types and methods mentioned in this guide
Generic Type Parameter
When you create a Collection
instance, you must specify a generic
type parameter to represent the type of data that models the documents
in your collection. To learn more about specifying a generic type parameter,
see the Collection Parameterization section of the guide on Databases and Collections.
We recommend that you define and use a custom type to model your
collection's data instead of using the Document
type.
Custom Data Model
You can use any Rust data type that implements the Serialize
and
Deserialize
traits from the serde
crate as the generic type
parameter for a Collection
instance. To implement the Serialize
and Deserialize
traits, you must include the following derive
attribute before defining a Rust type:
Custom Struct Example
The following code defines a sample Article
struct that implements
the serde
serialization traits:
struct Article { title: String, date: DateTime, content: String, content_embeddings: Vector, }
Tip
Vector Type
Starting in bson
library v2.14, you can use the
bson::binary::Vector type
to represent vectors of numeric values.
Since this type is serialized as a BSON binary vector, usage of
Vector
can improve storage efficiency. To learn more, see the
BSON specification.
The following code accesses the articles
collection with
the Article
struct as its generic type parameter:
let my_coll: Collection<Article> = client .database("db") .collection("articles");
Because the Collection
instance is parameterized with the
Article
struct, you can perform CRUD operations with this type.
The following code inserts an Article
instance into the collection:
let article = Article { title: "Maintaining Your Garden in Winter".to_string(), date: DateTime::now(), content: "As fall winds down, you might be wondering what you should be doing in your garden in the coming months ...".to_string(), content_embeddings: Vector::Float32(vec! [0.01020927,-0.011224265,0.015686288,-0.018586276,-0.023160344]) }; my_coll.insert_one(article).await?;
Multiple Parameterizations
If your collection contains multiple schemas, you can define a custom
type to model each data type and create clones of the original
Collection
instance for each type. You can create clones of a
Collection
instance by using the clone_with_type()
method.
Suppose you originally parameterized a collection with a struct
called Square
, but you later realize that you want to insert a different
type of data, modeled by the Circle
struct, into the collection.
The following code parameterizes a collection with the Square
type,
then creates a clone of the collection that is parameterized with the
Circle
type:
let shapes_coll: Collection<Square> = client .database("db") .collection("shapes"); // ... perform some operations with Square let shapes_coll: Collection<Circle> = shapes_coll.clone_with_type(); // ... perform some operations with Circle
Custom Serialization
You can modify the default serialization and deserialization behavior of
the Rust driver by using attributes from the serde
crate.
Attributes are optional pieces of metadata attached to fields of
structs or variants of enums.
The serde
crate provides the serialize_with
and
deserialize_with
attributes, which take helper functions as values.
These helper functions customize serialization and deserialization on
specific fields and variants. To specify an attribute on a field,
include the attribute before the field definition:
struct MyStruct { field1: String, // ... other fields }
In the following sections, you can find examples that use helper
types from the bson
library to achieve common serialization tasks.
The examples show the following approaches:
BSON 3.0: Uses the
serde_as
annotation provided by theserde_with
crate, which offers additional flexibility and composition capabilitiesBSON 2.x: Uses the traditional
serialize_with
helper functions
BSON 2.15 is the default version. Choose the approach that matches your BSON crate version.
To use BSON 3.0 in your application, enable it as a feature in your
project's Cargo.toml
, similar to the following:
[dependencies.mongodb] version = "3.3.0" features = ["bson-3"]
When you enable BSON 3.0, you can use serde_as
. To use serde_as
, you must
import it in your application, as shown in the following code:
use serde_with::serde_as;
To see a full list of Serde helper functions, see the serde_helpers API documentation.
Serialize a String as an ObjectId
You might want to represent the _id
field in a document as a hexadecimal
string in your struct. To convert the hexadecimal string to the ObjectId
BSON type, select the BSON 3.0 (serde_as) or BSON 2.x (serialize_with)
tab for corresponding code examples depending on your BSON crate version:
Use the bson::serde_helpers::object_id::FromHexString
type with the serde_as
annotation:
struct Order { _id: String, item: String, }
Use the serialize_hex_string_as_object_id
helper function:
struct Order { _id: String, item: String, }
To see how the driver serializes a sample Order
struct to BSON,
select from the following Struct and BSON tabs:
let order = Order { _id: "6348acd2e1a47ca32e79f46f".to_string(), item: "lima beans".to_string(), };
{ "_id": { "$oid": "6348acd2e1a47ca32e79f46f" }, "item": "lima beans" }
Serialize a DateTime as a String
You might want to represent a DateTime
field value in a document as an
ISO-formatted string in BSON. Select the BSON 3.0(serde_as) or
BSON 2.x (serialize_with) tab for corresponding code examples for
this conversion.
Use the bson::serde_helpers::datetime::AsRfc3339String
type with the serde_as
annotation:
struct Order { item: String, delivery_date: DateTime, }
Use the serialize_bson_datetime_as_rfc3339_string
helper function:
struct Order { item: String, delivery_date: DateTime, }
Select the BSON 3.0(serde_as) or BSON 2.x (serialize_with)
tab to see how the driver serializes a sample Order
struct to BSON.
let order = Order { item: "lima beans".to_string(), delivery_date: DateTime::now(), };
{ "_id": { ... }, "item": "lima beans", "delivery_date": "2023-09-26T17:30:18.181Z" }
Serialize a u32 as an f64
You might want to represent a u32
field value in a document as
an f64
, or Double
, type in BSON. Select the BSON 3.0(serde_as)
or BSON 2.x (serialize_with) tab for corresponding code
samples to specify this conversion.
Use the bson::serde_helpers::u32::AsF64
type with the serde_as
annotation:
struct Order { item: String, quantity: u32, }
Use the serialize_u32_as_f64
helper function:
struct Order { item: String, quantity: u32, }
Note
The BSON Double
representation of a u32
value appears
the same as the original value.
Other Attributes and Modules
In addition to helper functions, the bson
library provides modules
that handle both serialization and deserialization. To select a module
to use on a specific field or variant, set the value of the with
attribute to the name of the module:
struct MyStruct { field1: u32, // ... other fields }
For a full list of these modules, see the serde_helpers API documentation.
The serde
crate provides many other attributes to customize
serialization. The following list describes some common attributes and
their functionality:
rename
: serialize and deserialize a field with a specified name instead of the Rust struct or variant nameskip
: do not serialize or deserialize the specified fielddefault
: if no value is present during deserialization, use the default value fromDefault::default()
For a full list of serde
attributes, see the serde Attributes
API Documentation.
Additional Information
To learn more about BSON types, see BSON Types in the Server manual.
For more examples that demonstrate serde
functionality, see the
Structuring Data with Serde in Rust Developer Center
article.
To learn more about the Serde framework, see the Serde documentation.
API Documentation
To learn more about the methods and types mentioned in this guide, see the following API documentation:
serialize_with Serde attribute
deserialize_with Serde attribute
with Serde attribute