how can I flatten an enum to a special case when the explicit cases don't match

Viewed 339

I'd like it so when the case is unknown, it will be associated with the last case

#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(untagged)]
pub enum Action {
    Action1,
    Action2,
    Action3,
    Other(String), // when not known it should be here
}

I've tried using the directive

#[serde(untagged)]

but then it doesn't serialize properly

let b = Action::Action1;
let s = serde_json::to_string(&b);
let ss = s.unwrap();
println!("ss {:#?}", &ss);
let val = serde_json::to_value(b);
println!("ss {:#?}", &val);

results in

ss "null"
ss Ok(
    Null,
)

Playground link

1 Answers

I can think of two options that build off each other.

First use From to turn this into a string every time you serialize and then From to turn it back into your own type. This requires you to convert every time you serialize and deserialize but will accomplish your goal.

If you want to make the API a little cleaner at the cost of doing more work you can implement serialize and deserialize yourself. Here are some references on how to do that:

  1. Custom Serialization
  2. Implementing Serialize
  3. Implementing Deserialize

As a second option you can offload the custom serialization and deserialization if your willing to add another dependency of serde_with.

According to its docs:

De/Serializing a type using the Display and FromStr traits, e.g., for u8, url::Url, or mime::Mime. Check DisplayFromStr or serde_with::rust::display_fromstr for details.

Related