简体   繁体   English

在 Rust 中使用带有 serde 的嵌套枚举/结构序列化/反序列化 CSV

[英]Serialize/Deserialize CSV with nested enum/struct with serde in Rust

I want to serialize/deserialize a CSV file with variable row length and content, like the following:我想序列化/反序列化具有可变行长度和内容的 CSV 文件,如下所示:

./test.csv ./test.csv

Message,20200202T102030,Some message content
Measurement,20200202T102031,10,30,40,2
AnotherMeasurement,20200202T102034,0,2

In my opinion, the easiest way to represent this is the following enum :在我看来,表示这一点的最简单方法是以下enum

#[derive(Debug, Serialize, Deserialize)]
pub enum Record {
    Message { timestamp: String, content: String }, // timestamp is String because of simplicity
    Measurement { timestamp: String, a: u32, b: u32, c: u32, d: u32 },
    AnotherMeasurement { timestamp: String, a: u32, b: u32 },
}

Cargo.toml货物.toml

[dependencies]¬
csv = "^1.1.6"¬
serde = { version = "^1", features = ["derive"] }

Running the following运行以下

main.rs主要.rs

fn example() -> Result<(), Box<dyn Error>> {
    let mut rdr = csv::ReaderBuilder::new()
        .has_headers(false)
        .delimiter(b',')
        .flexible(true)
        .double_quote(false)
        .from_path("./test.csv")
        .unwrap();
    for result in rdr.deserialize() {
        let record: Record = result?;
        println!("{:?}", record);
    }
    Ok(())
}

fn write_msg() -> Result<(), Box<dyn Error>> {
    let msg = Record::Message {
        timestamp: String::from("time"),
        content: String::from("content"),
    };
    let mut wtr = csv::WriterBuilder::new()
        .has_headers(false)
        .flexible(true)
        .double_quote(false)
        .from_writer(std::io::stdout());
    wtr.serialize(msg)?;
    wtr.flush()?;
    Ok(())
}

fn main() {
    if let Err(err) = example() {
        println!("error running example: {}", err);
    }
    if let Err(err) = write_msg() {
        println!("error running example: {}", err);
    }
}

prints印刷

error running example: CSV deserialize error: record 0 (line: 1, byte: 0): invalid type: unit variant, expected struct variant
error running example: CSV write error: serializing enum struct variants is not supported

Is there an easy solution to do this with serde and csv ?使用serdecsv有一个简单的解决方案吗? I feel like I missed one or two serde attributes, but I was not able to find the right one in the documentation yet.我觉得我错过了一两个serde属性,但我还没能在文档中找到正确的属性。

EDITS编辑

Netwave suggested adding the #[serde(tag = "type")] attribute. Netwave 建议添加#[serde(tag = "type")]属性。 Serializing now works, Deserializing gives the following error:序列化现在可以工作,反序列化会出现以下错误:

error running example: CSV deserialize error: record 0 (line: 1, byte: 0): invalid type: string "Message", expected internally tagged enum Record

Research I did that did not lead to a solution yet我所做的研究尚未找到解决方案

Is there a way to "flatten" enums for (de)serialization in Rust? 有没有办法在 Rust 中“扁平化”枚举以进行(反)序列化?

https://docs.rs/csv/1.1.6/csv/tutorial/index.html https://docs.rs/csv/1.1.6/csv/tutorial/index.html

Custom serde serialization for enum type 枚举类型的自定义 serde 序列化

https://serde.rs/enum-representations.html https://serde.rs/enum-representations.html

Make yourenum tagged (internally tagged specifically):使您的枚举标记(内部专门标记):

#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum Record {
    Message { timestamp: String, content: String }, // timestamp is String because of simplicity
    Measurement { timestamp: String, a: u32, b: u32, c: u32, d: u32 },
    AnotherMeasurement { timestamp: String, a: u32, b: u32 },
}

Playground 操场

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM