Comments (8)
@surfingtomchen the approach I am using is this one:
use serde::Serializer;
use wither::bson::oid::ObjectId;
pub fn serialize_object_id<S>(object_id: &Option<ObjectId>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match object_id {
Some(ref object_id) => serializer.serialize_some(object_id.to_string().as_str()),
None => serializer.serialize_none()
}
}
#[derive(Debug, Model, Serialize, Deserialize)]
pub struct Foo {
#[serde(
rename = "_id",
skip_serializing_if = "Option::is_none",
serialize_with = "serialize_object_id"
)]
pub id: Option<ObjectId>,
}
I am not sure if this is the best approach but you can try it out.
from wither.
@surfingtomchen I think you might be misunderstanding the output when you're printing a BSON document. Try running the following code in a clean Rust project:
[dependencies]
mongodb = "1.1.1"
serde = { version = "1.0.116", features = ["derive"] }
tokio = { version = "0.2.22", features = ["macros", "rt-threaded"] }
use mongodb::{bson::oid::ObjectId, Client};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone)]
struct User {
/// The ID of the model.
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
id: Option<ObjectId>,
nick: String,
}
#[tokio::main]
async fn main() {
let client = Client::with_options(Default::default()).unwrap();
let coll = client.database("foo").collection("bar");
let user = User {
id: Some(ObjectId::new()),
nick: "saghm".into(),
};
coll.insert_one(mongodb::bson::to_document(&user).unwrap(), None)
.await
.unwrap();
let user = coll.find_one(None, None).await.unwrap().unwrap();
println!("{:#?}", user);
}
The output of this short program will show that the ObjectId is correctly getting round-tripped as a bson ObjectId value:
Document({"_id": ObjectId(ObjectId(5f60410c00efcb5f004b12a3)), "nick": String("saghm")})
The confusion you're having stems from the fact that our Display
implementation for BSON uses JSON formatting for the values. However, JSON doesn't have many of the types that BSON has, including ObjectId. If we used "_id": "5f5ae5b400f0368a00715eca"
like you suggest in your original issue description, it would be indistinguishable from if the _id
field was actually a BSON string rather than an ObjectId. To alleviate this, we use a format called Extended JSON, which defines how to represent non-JSON values using JSON objects with $
-prefixed keys. The extended JSON definition of ObjectId
is to use an object with a single $oid
field with a hex-encoded value representing the bytes it contains. To be clear, the data is being sent to the database as a raw ObjectId, not as a document with the $oid
field; you can verify this by connecting to the database with the shell and inspecting the data manually.
from wither.
@thedodd @saghm Thank you for your clarification. I totally understand and agree with you why the ObjectId should be displayed as Extended JSON with $oid inside it to have Mongo read it properly.
I guess maybe current issue should not be described as bug but a feature request. Because when I use the mongoose for Node.js, if I defined id as ObjectId, mongoose will automatically displayed as string once output it to the http response. That's why @thedodd suggest me to use another structure to store the value as String. It will solve the problem but have a little bit inconvience.
I believe Wither plays the same role in Rust as Mongoose to Node.js. Please consider the feature request, thanks.
from wither.
@surfingtomchen good, glad we were able to find an immediate solution. For a long-term change as you mentioned, I think it would be best to open an issue for this in the BSON crate, as that is where the type lives. I leave that up to you. It may need some design, perhaps a special function ... not sure.
Let me know if there is anything else to discuss. Otherwise, mind closing the issue?
Yes, the issue will be closed
from wither.
@surfingtomchen are you getting an actual error somewhere in your code? {"$oid": "..."}
is how BSON encodes an ObjectId, so I don't necessarily see a problem here.
from wither.
"data": {
"_id": {
"$oid": "5f5ae5b400f0368a00715eca"
},
"nick": "Tm999y"
}
how to convert to
"data": {
"_id": "5f5ae5b400f0368a00715eca",
"nick": "Tm999y"
}
I tried flatten of serde, but it shows
"data": {
"$oid": "5f5ae5b400f0368a00715eca",
"nick": "Tm999y"
}
and can not rename after flattern
from wither.
@surfingtomchen I understand. What I am trying to communicate however is that the representation you are seeing is correct. When you encode a BSON ObjectId as extended JSON, as described here, that is what you get.
What you are seeing is an issue with this BSON library (https://github.com/mongodb/bson-rust). There is probably lots more discussion on this very topic over there.
HOWEVER, an immediate solution would be to create a struct which holds your ObjectId
field as a String
, and then when you write that struct as JSON, it will render the way that you want it to.
That should resolve your issue. If you think changes are needed to the BSON lib, please open an issue there. Cheers!
from wither.
@surfingtomchen good, glad we were able to find an immediate solution. For a long-term change as you mentioned, I think it would be best to open an issue for this in the BSON crate, as that is where the type lives. I leave that up to you. It may need some design, perhaps a special function ... not sure.
Let me know if there is anything else to discuss. Otherwise, mind closing the issue?
from wither.
Related Issues (20)
- thread 'main' panicked at 'there is no timer running, must be called from the context of a Tokio 0.2.x runtime' HOT 4
- Mongo Rust driver upgrade coming HOT 6
- wither::Migration extensions HOT 6
- How to run aggregations? HOT 3
- Document references / cross-collection population HOT 8
- Batch document creation? HOT 3
- How to Specify Enum Literals? HOT 4
- Nice way to collect a cursor? HOT 2
- Docs cleanup & updates
- Add `update_many` method HOT 3
- [Docs] How does projection work in Rust? HOT 1
- Using basic example HOT 11
- [Enhancement] add created at and updated at timestamps HOT 1
- Upgrade to mongo driver 2.0 HOT 1
- Re-introduce IndexModel from the official driver
- Partial updates and typed documents
- Non-ObjectId _id fields HOT 1
- Call to action HOT 6
- Wither not working with mongodb operating in async-std HOT 3
- Mongodb _id Serialized to Id
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from wither.