Read CSV to struct, add extra fields



examples/csv/csv-struct-extra-fields/Cargo.toml
[package]
name = "handle-csv"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
csv = "1.2.2"
serde = { version = "1.0", features = ["derive"] }

examples/csv/csv-struct-extra-fields/out.txt
Record { name: "Mercury", distance: 0.4, mass: 0.055, text: "abc", float: 0.0, person: Person { name: "", birth_year: 0 } }
Record { name: "Venus", distance: 0.7, mass: 0.815, text: "abc", float: 0.0, person: Person { name: "", birth_year: 0 } }
Record { name: "Earth", distance: 1.0, mass: 1.0, text: "abc", float: 0.0, person: Person { name: "", birth_year: 0 } }
Record { name: "Mars", distance: 1.5, mass: 0.107, text: "abc", float: 0.0, person: Person { name: "", birth_year: 0 } }
Record { name: "Ceres", distance: 2.77, mass: 0.00015, text: "abc", float: 0.0, person: Person { name: "", birth_year: 0 } }
Record { name: "Jupiter", distance: 5.2, mass: 318.0, text: "abc", float: 0.0, person: Person { name: "", birth_year: 0 } }
Record { name: "Saturn", distance: 9.5, mass: 95.0, text: "abc", float: 0.0, person: Person { name: "", birth_year: 0 } }
Record { name: "Uranus", distance: 19.6, mass: 14.0, text: "abc", float: 0.0, person: Person { name: "", birth_year: 0 } }
Record { name: "Neptune", distance: 30.0, mass: 17.0, text: "abc", float: 0.0, person: Person { name: "", birth_year: 0 } }
Record { name: "Pluto", distance: 39.0, mass: 0.00218, text: "abc", float: 0.0, person: Person { name: "", birth_year: 0 } }
Record { name: "Charon", distance: 39.0, mass: 0.000254, text: "abc", float: 0.0, person: Person { name: "", birth_year: 0 } }
---
Mars
1.5
0.107
abc
0

0

examples/csv/csv-struct-extra-fields/planets.csv
Planet name,Distance (AU),Mass
Mercury,0.4,0.055
Venus,0.7,0.815
Earth,1,1
Mars,1.5,0.107
Ceres,2.77,0.00015
Jupiter,5.2,318
Saturn,9.5,95
Uranus,19.6,14
Neptune,30,17
Pluto,39,0.00218
Charon,39,0.000254


examples/csv/csv-struct-extra-fields/src/main.rs
use std::error::Error;
use std::fs::File;

#[derive(Debug, serde::Deserialize)]
struct Person {
    name: String,
    birth_year: u16,
}

#[derive(Debug, serde::Deserialize)]
struct Record {
    #[serde(rename = "Planet name")]
    name: String,

    #[serde(rename = "Distance (AU)")]
    distance: f32,

    #[serde(rename = "Mass")]
    mass: f32,

    #[serde(default = "get_text")]
    text: String,

    #[serde(default = "get_zero")]
    float: f32,

    #[serde(default = "get_person")]
    person: Person
}
fn get_text() -> String {
    "abc".to_string()
}
fn get_zero() -> f32 {
    0.0
}
fn get_person() -> Person {
    Person { name: "".to_string(), birth_year: 0 }
}

fn main() {
    let filepath = "planets.csv";
    let result = read_file(filepath);
    match result {
        Ok(rows) => {
            for row in &rows {
                println!("{:?}", row);
            }
            println!("---");
            println!("{}", rows[3].name);
            println!("{}", rows[3].distance);
            println!("{}", rows[3].mass);
            println!("{}", rows[3].text);
            println!("{}", rows[3].float);
            println!("{}", rows[3].person.name);
            println!("{}", rows[3].person.birth_year);
        },
        Err(err) => panic!("Error: {}", err)
    }
}

fn read_file(filepath: &str) -> Result<Vec<Record>, Box<dyn Error>> {
    let mut records:Vec<Record> = vec![];
    match File::open(filepath) {
        Ok(file) => {
            let mut rdr = csv::Reader::from_reader(file);
            for result in rdr.deserialize() {
                let record: Record = result?;
                records.push(record);
            }
        },
        Err(error) => panic!("Error opening file {}: {}", filepath, error),
    }
    Ok(records)
}