问题
I'm parsing an INI-style file that uses integers for enumerators.
#[derive(Debug, Deserialize, Serialize)]
pub enum MyThing {
First = 0,
Second = 1,
Third = 2,
}
In the file, the value will get serialized like so:
thing=0
However, Serde by default matches against the variant name rather than the discriminant. Is custom-implementing Deserialize
the cleanest method?
回答1:
The Serde website has an entire example on how to serialize an enum as a number:
extern crate serde; extern crate serde_json; use std::fmt; macro_rules! enum_number { ($name:ident { $($variant:ident = $value:expr, )* }) => { #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum $name { $($variant = $value,)* } impl ::serde::Serialize for $name { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: ::serde::Serializer { // Serialize the enum as a u64. serializer.serialize_u64(*self as u64) } } impl<'de> ::serde::Deserialize<'de> for $name { fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: ::serde::Deserializer<'de> { struct Visitor; impl<'de> ::serde::de::Visitor<'de> for Visitor { type Value = $name; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("positive integer") } fn visit_u64<E>(self, value: u64) -> Result<$name, E> where E: ::serde::de::Error { // Rust does not come with a simple way of converting a // number to an enum, so use a big `match`. match value { $( $value => Ok($name::$variant), )* _ => Err(E::custom( format!("unknown {} value: {}", stringify!($name), value))), } } } // Deserialize the enum from a u64. deserializer.deserialize_u64(Visitor) } } } } enum_number!(SmallNumber { Zero = 0, One = 1, Two = 2, Three = 3, }); fn main() { use SmallNumber::*; let nums = vec![Zero, One, Two, Three]; // Prints [0,1,2,3] println!("{}", serde_json::to_string(&nums).unwrap()); assert_eq!(Two, serde_json::from_str("2").unwrap()); }
I would believe that this is the best way to do it as it's recommended by the crate authors themselves.
来源:https://stackoverflow.com/questions/49604190/how-do-i-configure-serde-to-use-an-enum-variants-discriminant-rather-than-name