Я использую ящики csv
и serde
для десериализации 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
пустым.
Вот ржавчина игровая площадка, показывающая проблему:
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());
}
Это действительно так?
@Stargateur Это не вопрос, я должен поддержать дело, невозможно исправить старые версии файлов в системе управления версиями. Спасибо за встраивание фрагмента кода.
Добавьте заголовок поля вручную до того, как это должны сделать считанные строки, используя 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);
}
Однако, что быстро и грязно.
У меня работает, я обнаружил, что могу просто has_headers(false)
пропустить строку заголовка, прежде чем передать ее читателю.
@ galop1n Это тоже работает, но обратите внимание, что ваша структура будет десериализована исключительно на основе порядка полей, а не имен в заголовке. (Что может быть хорошо для вашего варианта использования!)
@Stargateur Я добавил игровую площадку для ржавчины, чтобы продемонстрировать свою проблему. Это именно то, что вы поняли. содержимое csv такое же, но заголовок столбца «field3» отсутствует.