How do I serialize and deserialize a remote crate's enum as a number?
我一直在尝试使用
测试用例
cargo.toml
1 2 3 4 5 6 7 8 9 10 | [package] name ="serde_error" version ="0.1.0" authors = ["Jason Miller"] edition ="2018" [dependencies] serialport ="3.3.0" serde = { version ="1.0", features = ["derive"] } ron ="0.5.1" |
以下导致错误:
1 | 6:16: Expected identifier |
main.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] #[serde(remote ="serialport::DataBits")] pub enum DataBitsDef { #[serde(rename ="5")] Five, #[serde(rename ="6")] Six, #[serde(rename ="7")] Seven, #[serde(rename ="8")] Eight, } fn default_data_bits() -> serialport::DataBits { serialport::DataBits::Eight } #[derive(Debug, Serialize, Deserialize)] pub struct TransceiverSettings { pub vid: u16, pub pid: u16, pub baud_rate: u32, #[serde(default ="default_data_bits", with ="DataBitsDef")] pub data_bits: serialport::DataBits, } impl Default for TransceiverSettings { fn default() -> Self { Self { vid: 0x2341, pid: 0x0043, baud_rate: 115_200, data_bits: serialport::DataBits::Eight, } } } const TRX_CONFIG: &str =" ( vid: 0x2341, pid: 0x0043, baud_rate: 9600, data_bits: 7, ) "; fn main() { match ron::de::from_str::<TransceiverSettings>(&TRX_CONFIG) { Err(e) => eprintln!("{}", e), Ok(c) => println!("{:?}", c), } } |
奇怪的是,将
1 | TransceiverSettings { vid: 9025, pid: 67, baud_rate: 9600, data_bits: Seven } |
main.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] #[serde(remote ="serialport::DataBits")] pub enum DataBitsDef { #[serde(rename ="5")] Five, #[serde(rename ="6")] Six, #[serde(rename ="seven")] Seven, #[serde(rename ="8")] Eight, } fn default_data_bits() -> serialport::DataBits { serialport::DataBits::Eight } #[derive(Debug, Serialize, Deserialize)] pub struct TransceiverSettings { pub vid: u16, pub pid: u16, pub baud_rate: u32, #[serde(default ="default_data_bits", with ="DataBitsDef")] pub data_bits: serialport::DataBits, } impl Default for TransceiverSettings { fn default() -> Self { Self { vid: 0x2341, pid: 0x0043, baud_rate: 115_200, data_bits: serialport::DataBits::Eight, } } } const TRX_CONFIG: &str =" ( vid: 0x2341, pid: 0x0043, baud_rate: 9600, data_bits: seven, ) "; fn main() { match ron::de::from_str::<TransceiverSettings>(&TRX_CONFIG) { Err(e) => eprintln!("{}", e), Ok(c) => println!("{:?}", c), } } |
serde_repr
Serialize enum as number
Theserde_repr crate provides alternative derive macros that derive the same Serialize and Deserialize traits but delegate to the underlying representation of a C-like enum. This allows C-like enums to be formatted as integers rather than strings in JSON
1
2
3
4
5
6
7
8 #[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug)]
#[repr(u8)]
enum SmallPrime {
Two = 2,
Three = 3,
Five = 5,
Seven = 7,
}
相反,请遵循"如何使用Serde在反序列化过程中转换字段"中的建议?和如何使用Serde在序列化期间转换字段?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | use serde::{Deserialize, Serialize}; mod shim { use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; use serialport::DataBits; pub fn serialize(v: &DataBits, s: S) -> Result<S::Ok, S::Error> where S: Serializer, { use DataBits::*; let v: u8 = match v { Five => 5, Six => 6, Seven => 7, Eight => 8, }; v.serialize(s) } pub fn deserialize<'de, D>(d: D) -> Result<DataBits, D::Error> where D: Deserializer<'de>, { use DataBits::*; match u8::deserialize(d)? { 5 => Ok(Five), 6 => Ok(Six), 7 => Ok(Seven), 8 => Ok(Eight), o => Err(D::Error::custom(format_args!("Invalid value {}", o))), } } } #[derive(Debug, Serialize, Deserialize)] pub struct TransceiverSettings { pub vid: u16, pub pid: u16, pub baud_rate: u32, #[serde(default ="default_data_bits", with ="shim")] pub data_bits: serialport::DataBits, } |