2022/03/12
[Rust]zipcloudのAPIを使って郵便番号から住所を検索する
概要
郵便番号から住所を検索することがありますが、そのzipcloudはPublicなAPIを提供していて、それを利用してRustから検索できるようにしてみました。
※ 事前に利用規約を呼んで使ってください
Rustでの実装
必要なライブラリ
# レスポンス結果のjsonをパースするために使います
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
# httpリクエストを実行するために使います
http = "0.2"
hyper = { version = "0.14", features = ["client", "http2"] }
hyper-rustls = "0.23.0"
結果を格納する構造体です
#[derive(Clone, Debug, Deserialize)]
pub struct Response {
pub message: Option<String>,
pub results: Option<Vec<Address>>,
pub status: Option<i32>,
}
#[derive(Clone, Debug, Deserialize, PartialEq)]
pub struct Address {
pub address1: String,
pub address2: String,
pub address3: String,
pub kana1: String,
pub kana2: String,
pub kana3: String,
pub prefcode: String,
pub zipcode: String,
}
メイン部分です
use http::{Request, StatusCode, Version};
use hyper::body::Buf;
use hyper_rustls::HttpsConnectorBuilder;
use serde::Deserialize;
use std::io::Read;
pub async fn fetch_address(zipcode: &str) -> Result<Option<Address>> {
// hyperとhttpを使って、zipcloudにgetリクエストを投げます。
let uri = format!("https://zipcloud.ibsnet.co.jp/api/search?zipcode={}&limit=1", zipcode);
let request = Request::builder()
.version(Version::HTTP_11)
.method("GET")
.uri(uri)
.body(hyper::Body::empty())
.unwrap();
let connector = HttpsConnectorBuilder::new()
.with_native_roots()
.https_only()
.enable_http1()
.build();
let client = hyper::Client::builder().http2_only(false).build(connector);
let response = client.request(request).await?;
// レスポンスを結果の構造体にパースして返却します。
let response_status = response.status().clone();
let mut response_body = String::new();
hyper::body::aggregate(response.into_body())
.await?
.reader()
.read_to_string(&mut response_body)?;
if response_status == StatusCode::OK {
let response: Response = serde_json::from_str(&response_body)?;
if let Some(result) = response.results {
let address = result.get(0).unwrap();
Ok(Some(address.clone()))
} else {
Ok(None)
}
} else {
Err(Error::Gateway {
status_code: response_status.as_u16(),
reason: response_body,
})
}
}
作ったライブラリ
createは公開していませんが・・・githubにソースコードを公開しました。
以下のような感じで使います。(郵便番号100-0000
をもとに、千代田区の住所が取得できています。)
use zipcloud::Address;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let zipcode = "100-0000";
let address = zipcloud::fetch_address(zipcode).await.unwrap();
assert!(address.is_some());
assert_eq!(
Address {
address1: "東京都".to_owned(),
address2: "千代田区".to_owned(),
address3: "".to_owned(),
kana1: "トウキョウト".to_owned(),
kana2: "チヨタ\u{ff9e}ク".to_owned(),
kana3: "".to_owned(),
prefcode: "13".to_owned(),
zipcode: "1000000".to_owned()
},
address.unwrap()
);
Ok(())
}
以上です。
関連する記事
Concordiumノードをローカルで動かしてみた
Concordiumの調査のために、ローカルでソースコードをビルドしてノードを動かしてみました
[Rust]axumとdragonflyを使ったWebsocket Chatのサンプル実装
redis互換のdragonflyをPUBSUBとして利用して、Websocket Chatアプリのサンプル実装を行いました。
[Rust]TiDBを使ったサンプルアプリケーションの実装
RustからTiDBを使ったアプリケーションの実装を行いました。
[Rust]Google Cloud Storageを利用する
GCSやNFSのファイルを扱えるpackageをRustで実装しました。