我正在解析一个使用整数的INI风格的文件。
#[derive(Debug, Deserialize, Serialize)]
pub enum MyThing {
First = 0,
Second = 1,
Third = 2,
}
在文件中,值将按如下方式序列化:
thing=0
但是,Serde默认情况下与变体名称匹配,而不是与判别式匹配。自定义实现Deserialize
是最干净的方法吗?
答案 0 :(得分:3)
Serde网站有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()); }
我相信这是最好的方式,因为它是由箱子作者自己推荐的。