Structuring Data with Serde in Rust
Rate this article
This post details new upgrades in the
and BSON library to improve our integration with Serde. In the
, we discussed the trickiness of working with BSON, which has a dynamic schema, in Rust, which uses a static type system. The MongoDB Rust driver and BSON library use
to make the conversion between BSON and Rust structs and enums easier. In the 1.2.0 releases of these two libraries, we've included new Serde integration to make working directly with your own Rust data types more seamless and user-friendly.
For example, I'm working with the following struct that defines the schema of the data in my
I can also find a Student directly from my
I may decide that I want to insert a different type of data into the
studentscollection at some point. Although my
studentscollection is restricted to the
Studentdata type, I can easily create a clone of the
studentscollection with a new type parameter:
The default generic type for
Document. This means that any
Collectioncreated without a generic type will continue to find and return the
Documenttype, and any existing code that uses
Collectionwill be unaffected by these changes.
The 1.2.0 release also includes changes to the Rust BSON library that improve usability when working with Serde.
The BSON library now includes a set of functions that implement common strategies for custom serialization and deserialization when working with BSON. You can use these functions by importing them from the
serde_helpersmodule in the
bson-rustcrate and using the
deserialize_withattributes. A few of these functions are detailed below.
We've introduced a method for serializing a hex string into an
serialize_hex_string_as_object_id. I can annotate my
oidfield with this function using
Now, if I serialize an instance of the
Itemstruct into BSON, the
oidfield will be represented by an
ObjectIdrather than a
Since BSON doesn't have a specific UUID type, I'll need to convert this data into binary if I want to serialize into BSON. I'll also want to convert back to Uuid when deserializing from BSON. The
uuid_as_binarymodule in the
serde_helpersmodule can take care of both of these conversions. I'll add the following attribute to use this module:
Now, I can work directly with the Uuid type without needing to worry about how to convert it to and from BSON!
The BSON specification defines two integer types: a signed 32 bit integer and a signed 64 bit integer. This can prevent challenges when you attempt to insert data with unsigned integers into your collections.
Studentstruct from the previous example contains unsigned integers in the
test_scorefields. Previous versions of the BSON library would return an error if I attempted to serialize an instance of this struct into
Document, since there isn't always a clear mapping between unsigned and signed integer types. However, many unsigned integers can fit into signed types! For example, I might want to create the following student:
While the numbers in the
test_scoresfields are technically unsigned 32 bit integers, they can be converted to signed 32 bit integers without losing any data.
The 1.2.0 release of the BSON library no longer returns an error when attempting to serialize unsigned integers into BSON, and instead tries to perform a lossless conversion into one of the signed integer BSON types. If the unsigned integer cannot be converted to a signed 32 bit or 64 bit integer, serialization will still return an error.
Now, I can convert my student struct into a
I can use
println!to see the following
Serde is a powerful tool that provides lots of functionality for customizing the way you convert between different data formats. In the 1.2.0 releases of the Rust driver and BSON library, we've made it even easier to work directly with your Rust data types. If you're interested in more complex mapping capabilities, it's worth reading the Serde documentation on
. For more details on working with MongoDB in Rust, you can check out the documentation for the
. We also happily accept contributions in the form of Github pull requests - please see the section in our
for info on how to run our tests.