Calling web api with body as BSON?

How do i post to web api with body as BSON formatted? I have a struct and want to serialise to BSON and post to a web api. How can i do it in rust?

Thanks in advance

You do it the same way as you use json, except you use the bson crate instead of serde_json.

can you please give me an example how to do it with reqwest crate

Huh, the bson api is a bit awkward to use. Anyway, I think this should do it:

let body = reqwest::get("https://www.rust-lang.org")
    .await?
    .bytes()
    .await?;

let doc = bson::decode_document(&mut &body[..]).unwrap();
let parsed: YourType = bson::from_bson(bson::Bson::Document(doc)).unwrap();

thank you. You are showing how to get bson from web api. How do i post BSON document to web api using reqwest. Sorry i am newb to rust.

I guess it would be something like this:

let client = reqwest::Client::new();
let doc = /* create a document */;

let mut body = BytesMut::new();
bson::encode_document(&mut body, doc);

let res = client.post("your_url")
    .body(body.freeze())
    .send()
    .await?;

You can either create the document directly using the functions such as insert, or you can try to use to_bson to convert other types into a document. You'll have to do some sort of unwrapping to get a document out though, because it returns the Bson enum instead.

If you are not otherwise using async code, you can use the blocking module in reqwest, which provides the same functionality but without awaits.

Thank you very much. I will give a try.

I am getting this error

bson::encode_document(&mut body, doc);
   |     ^^^^^^^^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `bytes::bytes_mut::BytesMut`

Try this instead:

let client = reqwest::Client::new();
let doc = /* create a document */;

let mut body = Vec::new();
bson::encode_document(Cursor::new(&mut body), doc);

let res = client.post("your_url")
    .body(body)
    .send()
    .await?;

Thank you and it worked. I have a question deserializing this response OrderedDocument({"ProcessIdentification": BinData(4, 0x583817de199a0b418feaad63234f0a69), "ProcessInformation": String("Valorização - Vlz. p/ hist. p/ cart. I 22.222.

what is the equivalent rust type for uuid BinData(4, 0x583817de199a0b418feaad63234f0a69) how can i deserialize to this type

#[derive(Serialize, Deserialize, Debug)]
pub struct ProcessExecuteResult {
    pub ProcessIdentification: Vec<u8>,
    pub ProcessInformation: String,
}

I don't know, sorry.

Np. I managed to figure it out.

Here is what i did. If you think we can do better please let me know.

let id = doc.get("ProcessIdentification").unwrap();

match id {
    Bson::Binary(spec::BinarySubtype::Uuid,b) => println!("{:?}", Uuid::from_slice(&b[..])),
    _ => panic!("Invalid Uuid"),
}

Maybe non-answer to your question, but are you implementing both the api which expects BSON as payload format and its api?

Besides how its name look like, the BSON is not intended for general purpose data exchange format. It's originally made for the internal storage format of the MongoDB. That's why it has so many edge cases including special casing keys starts with "$" character.

If you want binary data exchange format with JSON-like structure, use MsgPack or CBOR format. If you're not an provider of that api, maybe the author already deceived from the name of the BSON, unless the api itself is of the MongoDB.

You are right. We are the providers and 90% of the web api supports Json and Bson. Remaining 10% is bson since we have binary data exchange. In .net there is a complete support for bson in client and server side. I am porting a .net command line application. I can’t change the provider. The sample what I gave accepts json header also. I realized lately. In few cases I need to send binary data. Thank you for the suggestion. Let me check whether CBOR is supported by .net web api.

I have checked with ,net and there is no built in support for CBOR. Needs lot of Work on the server side. So need to stick with bson for 10% cases.