最近Rustの勉強を始め,営業日や営業時間に関するプログラムをPythonからRustに書き換えています.そこで今回はrequwestで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"] }
次に,プログラム全体です.
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を利用します.
また今回は非同期に取得する必要が無いので,reqwest::blocking
を利用します.reqwestのexample通りにResponseオブジェクトのjsonメソッドに型パラメーターを指定してHashMapにしています.
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は内閣府のサイトのこちらからダウンロードできます.これは1955年から来年までの国民の祝日が表記されたcsvファイルです.このcsvはshift-jisで保存されているのですが,shift-jisのファイルの読み込み方を@benkiさんにコメントで教えて頂きました.~~テキストとして取得し,~~レスポンスをバイトで読み込み,encoding_rs::SHIFT_JIS.decode
で文字列に変換します.csvクレートのexample通りにas_bytesで変換してからcsvリーダーで読み込みます.PythonのようにBytesIOはいらないようです.
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があるのですが,使い方が分からなかったのでまたチャレンジしてみたいと思います.
{"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のダウンロード二つの方法で祝日情報を取得しました.
エンコーディングあたりが分かりませんでした.