How to convert bson to cbor with serde?

I want to convert bson to cbor. i'm using bson and serde_cbor crate.
Here's what I tried with serde_transcode


use mongodb::bson::{Document,Deserializer as BsonDeserializer}
use serde_cbor::{ Value, Serializer as CborSerializer};

...

let mut cbor_writer : Vec<u8> = Vec::new();

let d = BsonDeserializer::new(doc.into());
let s = CborSerializer::new(cbor_writer);

serde_transcode::transcode(d, s);

but when compiling, I'm getting this error:p

error[E0277]: the trait bound `serde_cbor::Serializer<Vec<u8>>: serde::ser::Serializer` is not satisfied
  --> src/keys.rs:36:51
   |
36 |                     serde_transcode::transcode(d, s);
   |                                                   ^ the trait `serde::ser::Serializer` is not implemented for `serde_cbor::Serializer<Vec<u8>>`
   | 
  ::: /home/noon/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-transcode-1.1.0/src/lib.rs:50:14
   |
50 |           S: ser::Serializer
   |              --------------- required by this bound in `transcode`
   |
   = help: the following implementations were found:
             <&'a mut serde_cbor::Serializer<W> as serde::ser::Serializer>

error[E0277]: the trait bound `serde_cbor::Serializer<Vec<u8>>: serde::ser::Serializer` is not satisfied
  --> src/keys.rs:36:21
   |
36 |                     serde_transcode::transcode(d, s);
   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `serde::ser::Serializer` is not implemented for `serde_cbor::Serializer<Vec<u8>>`
   |
   = help: the following implementations were found:
             <&'a mut serde_cbor::Serializer<W> as serde::ser::Serializer>

in help it shows <&'a mut serde_cbor::Serializer<W> as serde::ser::Serializer> is implemented but I'm still getting not implemented error. this is kinda confusing.

Note the &'a mut in the types the error message says the traits are implemented for. Try giving transcode &mut references instead of owned types. I checked sample code for transcode and that seems to be how it's intended to be used.

2 Likes

Thanks. following worked

let d = BsonDeserializer::new(doc.into());
let mut s = CborSerializer::new(cbor);

serde_transcode::transcode(d, &mut s).unwrap();
let cbor : Value = s.into_inner().into();

Well if you already have a bson::Document you don't even need transcode(), since a bson::Document itself impls Serialize. So you could just do let bytes = serde_cbor::to_vec(&doc); without unnecessarily going through any intermediate representations.

1 Like

serde_transcode hooks up a Deserializer and a Serializer without an intermediate representation. (That's its whole purpose.) But yes, if you already have some impl Serialize, you should serialize that rather than going through serde_transcode.

1 Like