简体   繁体   English

如何将远程板条箱的枚举序列化和反序列化为数字?

[英]How do I serialize and deserialize a remote crate's enum as a number?

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 .我一直在试图建立了以下配置serialport拉斯特箱与serde ,这样我就可以直观地提供7在我的配置为data_bits ,但将作为反序列化serialport::DataBits::Seven Unfortunately, it seemingly fails the moment I want it to be a number ( 7 ) and not a string ( seven ).不幸的是,当我希望它是一个数字( 7 )而不是一个字符串( seven )时,它似乎失败了。

Test case测试用例

cargo.toml货物.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:奇怪的是,将7写成seven成功并返回:

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 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. serde文档中给定的示例之一似乎与我的案例有关,但我还没有设法让它与我的设置一起工作。

Serialize enum as number 将枚举序列化为数字
The serde_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. serde_repr crate 提供替代派生宏,派生相同的 Serialize 和 Deserialize 特征,但委托给类 C 枚举的底层表示。 This allows C-like enums to be formatted as integers rather than strings in JSON这允许类似 C 的枚举被格式化为整数而不是 JSON 中的字符串

#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug)] #[repr(u8)] enum SmallPrime { Two = 2, Three = 3, Five = 5, Seven = 7, }

Support for #[serde(remote)] is not present in serde_repr 0.1.5. serde_repr 0.1.5 中支持#[serde(remote)] You will need to submit a pull request or issue to add support for it.您需要提交拉取请求或问题以添加对它的支持。

Instead, follow the advice in How to transform fields during deserialization using Serde?相反,请遵循如何在使用 Serde 进行反序列化期间转换字段中的建议 and How to transform fields during serialization using Serde?以及如何使用 Serde 在序列化期间转换字段? :

use serde::{Deserialize, Serialize};

mod shim {
    use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
    use serialport::DataBits;

    pub fn serialize<S>(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,
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将枚举序列化为数字并通过 serde-json 从数字反序列化? - How do I serialize an enum to a number and deserialize from a number via serde-json? 使用 Sled,我如何序列化和反序列化? - Using Sled, how do I serialize and deserialize? 如何在不包含枚举变量名称的情况下序列化枚举? - How do I serialize an enum without including the name of the enum variant? 如何在不分叉箱的情况下将#![feature(***)]添加到另一个箱的属性中? - How do I add #![feature(***)] to another crate's attributes without forking the crate? 如何使用 Serde 和 Petgraph 序列化和反序列化图形? - How do I serialize and deserialize a graph using Serde with Petgraph? 如何序列化或反序列化Arc <T> 在Serde? - How do I serialize or deserialize an Arc<T> in Serde? 如何使用 Serde 序列化和反序列化 Rust 中的元组? - How do I serialize and deserialize a tuple in Rust using Serde? 如何从字符串或数字反序列化无字段枚举? - How can I deserialize a fieldless enum from either a string or number? 在pest.rs、pesticast crate 中,我如何派生一个枚举字段? - In pest.rs, pest-ast crate, how do I derive an enum fields? 如何使用 serde 反序列化为特定的枚举变体? - How do I use serde to deserialize into a specific enum variant?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM