-
Notifications
You must be signed in to change notification settings - Fork 148
Description
I want to store my objects with uuid
identifier. One of my types looks like this:
#[derive(Deserialize, Serialize)]
pub struct Account<S: State> {
#[serde(rename = "_id")]
id: S::Id,
name: String,
balance: u64,
}
I use State
trait to express two states: New
and Saved
. It allows me to conveniently create an object of Account<New>
type without uuid
anywhere in the application, then id will be an unit type. So I can't directly use uuid_as_binary
attribute, this throws a build error. But that wouldn't be a problem if I could serialize an uuid to string. The doc says it serialize as string by default:
#[derive(Serialize, Deserialize)]
struct Foo {
// serializes as a String.
uuid: uuid::Uuid,
// ..
}
But when I save any object to db, then fetch all (for debug) I see it stores as binary format (with BinarySubtype::Generic
):
{ "_id": Binary(0x0, Nz6CfTaSS82T3q/pqjrhXA==), "name": "nano", "balance": 0 }
Ok, I can use binary as well, but then I can't find
an object by _id because when I try to do something like:
let uuid = Uuid::parse_str(id)?;
let filter = doc! { "_id": uuid };
let res = collection::<Account<Saved>>
.find_one(filter, None)
.await?;
The filter
document serializes as:
{ "_id": Binary(0x4, Nz6CfTaSS82T3q/pqjrhXA==) }
(with BinarySubtype::Uuid
)
How can these different serializations be made to work together? Of course I can use uuid_as_binary
attribute, but that will break my application's flexibility and invariant checking. Maybe there is some more suitable solution?
In addition, it seems to me that various serialization behavior is unintuitive and more like an implementation flaw. It would be more convenient if uuid was just (de)serialized as string by default.
I also think it would be great to implement this with type wrappers. For example, Uuid
will be (de)serialized as a string, and Binary(Uuid)
as binary data. Then it would be more convenient to use them in generic code.
Project's Cargo.toml dependencies
[dependencies]
rocket = { version = "0.5.0-rc.1", features = ["tls", "json", "uuid"] }
mongodb = { version = "2.0.0", features = ["bson-uuid-0_8"] }
uuid = { version = "0.8.2", features = ["v4"] }
serde = "1.0"