Multiple serde::Serialize implementations for custom structs

Viewed 834

Disclaimer: I'm a beginner with rust!

Lets assume I have the following to structs and I want the default json serialization from the derived Serialize traits


#[derive(Serialize)]
struct Address {
  zip:usize,
  street: String,
}

#[derive(Serialize)]
struct Person{
   name: String,
   age: usize,
   address: Address
}

In addition, I have implemented a custom serde::Serializer for a legacy format which takes any Serialize and internally forwards to the serialize methods when it encounters nested structs, enums, etc.


struct MySerializer {...}
impl Serializer for MySerializer {...}

Further, I defined a custom trait MyFormat that extends the Serialize trait and is supposed to work as a tag or something, i.e. if MySerializer encounters something that implements MyFormat, it should not use Serialize, but MyFormat instead.

trait MyFormat: Serialize {
 /// by default just use the normal Serialize trait method.
 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        Serialize::serialize(&self, serializer)
    }
}

impl MyFormat for Address {
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
    where
        S: Serializer,
    {
       // this can actually look much more complicated, e.g. some additional mapping will be done here.
       serializer.serialize_some(&self.zip)?;
       serializer.serialize_some(&"some extra field only present in this format")?;
       serializer.serialize_some(&self.street)?
    }
}

impl MyFormat for Person {}

Now the problem is, when I use the custom serializer, I can, on the most outer level control whether to use the derived Serialize, however, the moment I descent into the structure, the Serializer trait expects Serialize types in the trait method specification which I cannot narrow down to MyFormat, as that would violate the trait.

In the above example name and age are ok, as the format for primitive types is identical, however, the nested Address might require to "inject" some additional fields if serialized to MyFormat.

I assume I just miss some paradigm that lets me do that with traits in rust. In C++ I could use template specialization or SFINAE. Is there anything in rust that can solve this kind of problem?

Kind regards, Marti

0 Answers
Related