at backyard

Color my life with the chaos of trouble.

RustでCSVファイルを読み込んで、特定の構造体として利用する

個人的なメモ。Rust全然わからない人間なので、間違っている可能性あり。

tauriで書いたノートアプリで色々試していたときに、調べて書いていたのに不要になってしまったコードがあるので、ここにメモとして残しておくことで供養することにした。

github.com

CSVファイルを読み込んで構造体のインスタンスとして利用するメモ

下記のようなCSVがある。

id,title,text,createdAt,updatedAt
"1","Hello World","hello world!!","2022-07-16T23:10:06.766Z","2022-08-05T22:18:38.030Z"
・
・
・

このCSVをRustで読み込んで構造体のインスタンスとして利用したい。
(もしかしたらこの表現は正しくないかも。 obj.id, obj.title みたいな感じで使えるようにしたいという形です。)

まず下記のライブラリを利用する( Cargo.toml )。

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

で、実際に書いたコードは下記。

use csv;
use serde::Deserialize;
use std::error::Error;
use std::fs;

#[derive(Debug, Deserialize)]
struct Note {
    id: usize,
    title: String,
    text: String,
    created_at: String,
    updated_at: String,
}

fn read_csv(file_path: String) -> Result<Vec<Note>, Box<dyn Error>> {
    let mut note_list = Vec::new();

    let csv_text = fs::read_to_string(file_path)?;
    let mut rdr = csv::Reader::from_reader(csv_text.as_bytes());
    for result in rdr.records() {
        let record = result?.deserialize(None)?;
        note_list.push(record);
    }

    Ok(note_list)
}

fn main() {
    let note_list = read_csv("<CSVファイルのパス>".to_string()).unwrap();

    for note in note_list.iter() {
        println!("{:?}", note);
    }
}

一応メモとして残しておきたい箇所は下記。

let record = result?.deserialize(None)?;

これは読み込んだCSVレコードを構造体として扱うようにするところ。 result?.deserialize(None)?を使うことで言葉通りdeserializeしてくれる。
これをしないと StringRecord というtypeになってしまう。
なお、deserializeするために use serde::Deserialize; している。

一通りの使い方は公式ドキュメントにて。

docs.rs