Skip to content

Can't serialize/deserialize uuid properly #311

@nanoqsh

Description

@nanoqsh

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"

Metadata

Metadata

Assignees

No one assigned

    Labels

    tracked-in-jiraTicket filed in Mongo's Jira system

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions