[Rust]reqwestで祝日の取得(json, csv)

最近Rustの勉強を始め，営業日や営業時間に関するプログラムをPythonからRustに書き換えています．そこで今回は[requwest](https://github.com/seanmonstar/reqwest)でapiを通したjsonの受け取りとインターネット上のcsvファイルの読み込みの二つの方法で祝日情報を取得してみます．

まず，Cargo.tomlです．`encoding_rs`はshift-jisのcsvを読み込むのに利用します．

```
[dependencies]
csv = "1.1"
encoding_rs = "0.8"
reqwest = { version = "0.11", features = ["blocking", "json"] }
```

次に，プログラム全体です．

```rust
use std::collections::HashMap;
use std::error::Error;
use encoding_rs::SHIFT_JIS;


fn main() -> Result<(), Box<dyn Error>>{
    let year = "2020";
    let target1 = format!("https://holidays-jp.github.io/api/v1/{}/date.json", year);
    let resp_json = reqwest::blocking::get(target1)?
    .json::<HashMap<String, String>>()?;
    
    println!("{:?}", resp_json);

    let target2 = "https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv";
    let resp_content = reqwest::blocking::get(target2)?
    .bytes()?;

    let (decoded_content, _, _) = SHIFT_JIS.decode(&resp_content);

    let mut holiday_str_dict: HashMap<String, String> = HashMap::new();
    let mut rdr = csv::Reader::from_reader(decoded_content.as_bytes());
    for result in rdr.records() {
        let record = result?;
        holiday_str_dict.insert(record[0].into(), record[1].into());

    }

    println!("{:?}", holiday_str_dict);
    Ok(())
}
```

祝日取得のapiには[Holidays JP API](https://holidays-jp.github.io/)を利用します．
また今回は非同期に取得する必要が無いので，`reqwest::blocking`を利用します．reqwestのexample通りにResponseオブジェクトのjsonメソッドに型パラメーターを指定してHashMapにしています．

```rust
let year = "2020";
let target1 = format!("https://holidays-jp.github.io/api/v1/{}/date.json", year);
let resp_json = reqwest::blocking::get(target1)?
.json::<HashMap<String, String>>()?;
```
取得された祝日の表示が以下になります．

```
{"2020-05-05": "こどもの日", "2020-01-01": "元日", "2020-11-03": "文化の日", "2020-08-10": "山の日", "2020-09-22": "秋分の日", "2020-05-04": "みどりの日", "2020-01-13": "成人の日", "2020-05-06": "憲法記念日 振替休日", "2020-07-24": "スポー ツの日", "2020-02-23": "天皇誕生日", "2020-02-24": "天皇誕生日 振替休日", "2020-09-21": "敬老の日", "2020-05-03": "憲法 記念日", "2020-11-23": "勤労感謝の日", "2020-02-11": "建国記念の日", "2020-04-29": "昭和の日", "2020-03-20": "春分の日", "2020-07-23": "海の日"}
```

祝日取得のcsvは[内閣府のサイト](https://www8.cao.go.jp/chosei/shukujitsu/gaiyou.html)の[こちら](https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv)からダウンロードできます．これは1955年から来年までの国民の祝日が表記されたcsvファイルです．このcsvはshift-jisで保存されているのですが，shift-jisのファイルの読み込み方を@benkiさんにコメントで教えて頂きました．~~テキストとして取得し，~~レスポンスをバイトで読み込み，`encoding_rs::SHIFT_JIS.decode`で文字列に変換します．csvクレートのexample通りにas_bytesで変換してからcsvリーダーで読み込みます．PythonのようにBytesIOはいらないようです．

```rust
    let target2 = "https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv";
    let resp_content = reqwest::blocking::get(target2)?
    .bytes()?;

    let (decoded_content, _ , _) = SHIFT_JIS.decode(&resp_content);

    let mut holiday_str_dict: HashMap<String, String> = HashMap::new();
    let mut rdr = csv::Reader::from_reader(decoded_content.as_bytes());
    for result in rdr.records() {
        let record = result?;
        holiday_str_dict.insert(record[0].into(), record[1].into());

    }
```
取得された祝日の表示が以下になります．~~おそらくcsvがshift-jisで保存されているため祝日名が文字化けしています．Rustでエンコーディングを扱うには[encoding_rs](https://github.com/hsivonen/encoding_rs)があるのですが，使い方が分からなかったのでまたチャレンジしてみたいと思います．~~


```
{"2004/7/19": "海の日", "2011/5/5": "こどもの日", "2013/5/4": "みどりの日", "1958/11/3": "文化の日", "1996/10/10": "体育の日", "2004/3/20": "春分の日", "1959/4/29": "天皇誕生日", "2021/2/11": "建国記念の日", "2020/1/1": "元日", "1969/10/10": "体育の日", "1960/5/5": "こどもの日",...以下略
```

## まとめ
- reqwestを用いて，jsonの取得とcsvのダウンロード二つの方法で祝日情報を取得しました．
- ~~エンコーディングあたりが分かりませんでした．~~