fdeantoni / prost-wkt

Prost Well-Known-Types serialization and deserialization.
Apache License 2.0
76 stars 35 forks source link

`bytes` are serialized to `Vec<u8>` #10

Open rnbguy opened 2 years ago

rnbguy commented 2 years ago

Protobuf bytes should be deserialized to base64 strings.

Right now all Vec<_> are deserialized as they are. The Vec<u8> case should be handled differently.

rnbguy commented 2 years ago

My quick-fix is to use Serde field attributes.

pub fn base64_to_bytes<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
where
    D: Deserializer<'de>,
{
    let value: Option<&str> = Deserialize::deserialize(deserializer)?;
    Ok(match value {
        Some(value) => base64::decode(value).map_err(D::Error::custom)?,
        None => vec![],
    })
}

/// Serialize bytes to base64 string.
pub fn bytes_to_base64<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
{
    serializer.serialize_str(&base64::encode(bytes))
}

And then,

    #[serde(
        serialize_with = "bytes_to_base64",
        deserialize_with = "base64_to_bytes"
    )]
    pub bytes: ::prost::alloc::vec::Vec<u8>,
rnbguy commented 2 years ago

I found serde_with which can be used with field_attributes for data: ::prost::alloc::vec::Vec<u8>.

config.field_attribute("data", "#[serde(with = \"serde_with::As::<serde_with::base64::Base64>\")]");

or for repeated_data: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec<u8>>

config.field_attribute("repeated_data", "#[serde(with = \"serde_with::As::<Vec<serde_with::base64::Base64>>\")]");