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

问题描述 投票:3回答:1

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

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

这就是它在Rust中的映射方式,用读者的.flexible(true)读取它:

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

如果CSV有,field3标题行,一切正常。但有些文件没有它,我找不到解决方案让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());
}
csv rust serde
1个回答
3
投票

使用headers()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);
}

然而,那又快又脏。

© www.soinside.com 2019 - 2024. All rights reserved.