当 header 行中可能没有最后一个列名时,使用 Serde 反序列化 CSV

Deserializing a CSV with Serde when the header row may not have the last column name in it

我正在使用 csvserde crate 反序列化 csv 文件。问题是最后一个字段实际上是一个逗号分隔的列表。

field1,field2,field3
xx, xx, str1, ..., strN
xx, xx,
xx, xx, str1, ..., strM

这就是它在 Rust 中的映射方式,在 reader:

上用 .flexible(true) 读取它
#[derive(Debug, Deserialize)]
struct Row {
  field1: isize,
  field2: isize,
  field3: Vec<String>,
}

如果 CSV 包含 ,field3 和 header 行,一切正常。但是有些文件没有它,我找不到让 serde 仍然填充 Vec 的解决方案。我所能做的就是 #[serde(default)]field3 空着。

这里有一个锈 playground 显示问题:

extern crate csv;
#[macro_use]
extern crate serde_derive;

#[derive(Debug, Deserialize)]
struct Row {
    field1: String,
    field2: String,
    #[serde(default)]
    field3: Vec<String>,
}

fn test(str: String) {
    let mut reader = csv::ReaderBuilder::new()
        .flexible(true)
        .from_reader(str.as_bytes());

    for row in reader.deserialize() {
        if let Ok(row) = row {
            let row: Row = row;
            println!("{:?}", row);
        }
    }
}

fn main() {
    let csv_data = "
field1,field2,field3
xx,yy,one,two,three
zz,ww,
aa,bb
cc,dd,foo,bar,ban
";
    println!("With full header");
    test(csv_data.to_string());

    let csv_alt_data = "
field1,field2
xx,yy,one,two,three
zz,ww,
aa,bb
cc,dd,foo,bar,ban
";
    println!("With incomplet header");
    test(csv_alt_data.to_string());
}

在读取行之前手动添加字段 header,使用 headers() and set_headers():

let rdr = reader.headers().unwrap();
if let None = rdr.get(2) {
    let mut rdr = rdr.clone();
    rdr.push_field("field3");
    reader.set_headers(rdr);
}

然而,那又快又脏。