I have been trying to setup the following configuration for the serialport crate in Rust with serde, so I can intuitively supply 7 in my config for data_bits, but it will be deserialized as serialport::DataBits::Seven. Unfortunately, it seemingly fails the moment I want it to be a number (7) and not a string (seven).
Test case
cargo.toml
[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" The following results in the error:
6:16: Expected identifier main.rs
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), } } Oddly enough, writing 7 as seven succeeds and returns:
TransceiverSettings { vid: 9025, pid: 67, baud_rate: 9600, data_bits: Seven } main.rs
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
One of the given examples in the serde documentation seems relevant to my case, but I haven't managed to get it working with my setup.
Serialize enum as number
Theserde_reprcrate 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#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug)] #[repr(u8)] enum SmallPrime { Two = 2, Three = 3, Five = 5, Seven = 7, }