Как добавить дополнительную точку данных в экземпляр структуры при записи ее в файл с помощью Serde?

У Person есть first_name и last_name. Как добавить time экспорта в CSV при записи экземпляра Person в CSV?

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

use std::time::{SystemTime, UNIX_EPOCH};

#[derive(Debug, Serialize, Deserialize)]
struct Person {
    first_name: String,
    last_name: String,
}

fn current_ms() -> u64 {
    let since_the_epoch = &SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
    let ms = since_the_epoch.as_secs() * 1000 + since_the_epoch.subsec_nanos() as u64 / 1_000_000;
    ms
}

fn main() {
    let person = Person {
        first_name: "Craig".to_string(),
        last_name: "David".to_string(),
    };
    let file_path = std::path::Path::new("test.csv");
    let mut wtr = csv::Writer::from_path(file_path).unwrap();
    wtr.serialize(&person).unwrap();
    println!("{}", current_ms());
}

Приведенный выше код приводит к:

>>> cat test.csv
first_name,last_name
Craig,David

Моя цель - создать файл в формате:

>>> cat test.csv
time,first_name,last_name
1527661792118,Craig,David

В атрибутах Serde нет возможности добавить дополнительное поле. В приведенном выше примере структура Person не содержит значения time. Значение time требуется только при записи данных в CSV.


person Greg    schedule 30.05.2018    source источник
comment
Я полагаю, что на ваш вопрос ответили ответы Как преобразовать поля во время сериализации с помощью Serde?. Если вы не согласны, измените свой вопрос, чтобы объяснить различия. В противном случае мы можем пометить этот вопрос как уже отвеченный.   -  person Shepmaster    schedule 30.05.2018
comment
@Shepmaster Я обновил сообщение, чтобы объяснить, почему атрибуты serde не кажутся решением.   -  person Greg    schedule 30.05.2018
comment
Вы прочитали обе части ответа? Я знаю, что это очень длинный ответ, но прочитайте часть, чтобы создать отдельную структуру.   -  person Shepmaster    schedule 30.05.2018
comment
Я реорганизовал этот ответ, чтобы было ясно, что представлены два решения.   -  person Shepmaster    schedule 30.05.2018
comment
@Шепмастер Спасибо! Мне потребовалось некоторое время, чтобы понять, как работает ваше решение, но в конце концов я его получил :)   -  person Greg    schedule 30.05.2018


Ответы (1)


Если вы не хотите добавлять столбец временной метки в Person, вы можете создать для него отдельную структуру, а затем объединить их в кортеж:

#[derive(Debug, Deserialize, Serialize)]
struct Timestamp {
    time: u64,
}

impl Timestamp {
    fn now() -> Timestamp {
        Timestamp { time: current_ms() }
    }
}

fn main() {
    let person = Person {
        first_name: "Craig".to_string(),
        last_name: "David".to_string(),
    };
    let person_and_time = (Timestamp::now(), person);
    let file_path = std::path::Path::new("test.csv");
    let mut wtr = csv::Writer::from_path(file_path).unwrap();
    wtr.serialize(&person_and_time).unwrap();
}
person Peter Hall    schedule 30.05.2018