【Javascript】郵便番号から自動で住所を表示させる方法

Javascriptを使った小技を紹介します。

郵便番号を入力すると都道府県名・市町村名・町域名まで自動で取得する方法です。

(2018/4/30追記) SSL対応化についての記事を投稿したので、SSL対応する場合はそちらも参考にして下さい。

(2018/11/27追記) 新しいサイトにも掲載しました。コードの解説と SSL 対応の方法をまとめましたので、こちらも参考にして頂ければと思います。

今回は自前のデータベースではなく、株式会社アイビスさんが運営しているZipCloudというサービスを活用させて頂いております。
この場を借りて御礼申し上げます。


ソースコード

まずは、ソースコードを提示します。
DBがAPIで提供されているので非常に簡潔なコードで書くことができます。

<Javascript>

<script><!--
var getAddName = function( $addNum ){
	var _zipcloudAPI = document.body.appendChild(document.createElement("script"));
		_zipcloudAPI.src = "http://zipcloud.ibsnet.co.jp/api/search?zipcode=" + $addNum + "&callback=getAddNameByZipcloudAPI";
	document.body.removeChild(_zipcloudAPI);
};
var getAddNameByZipcloudAPI = function( $getAdd ){
	var _addFormatted  = "";
	if($getAdd.status == 200){
			_addFormatted += $getAdd.results[0].address1; // 都道府県名
			_addFormatted += $getAdd.results[0].address2; // 市町村名
			_addFormatted += $getAdd.results[0].address3; // 町域名
	}
	document.getElementById("add_name").value = _addFormatted;
};
//--></script>

<HTML(フォーム部)>

<P>郵便番号<BR>
〒<input size="20" type="text" name="zipcode" maxlength="9" type="tel" onchange="javascript:getAddName(this.value)">
</P>
<P>住所<BR>
<input size="30" type="text" name="address" id="add_name">
</P>

<実行結果>

郵便番号

住所

コードの解説

HTMLは割愛します。分からない方はINPUTタグについてググって下さい。

まず、今回の肝となるのがZipCloudへのリクエストとその返答の受け取り方です。

自分のドメイン内であれば非同期通信のXHRが使えますが、今回は外部APIなのでその手法は使えません。
(ZipCloudがXHR Level2対応しているものだと勘違いしておりハマりました(笑))

なので、この場合はJSONPという方法を使います。
簡単に云えば指定した関数名でJSON形式の引数を取ってコールするコードを返して貰う方法です。
これならばクロスドメインに対応していないAPIとやり取りができます。

※クロスドメインでの非同期通信(XHR)はサーバ側(API提供側)での設定が必須です。

JSONPの仕組み

今回使うZipCloudのAPIで解説します。

まず、http://zipcloud.ibsnet.co.jp/api/search?zipcode=7830060&callback=jsonpにアクセスすると以下のような文字列が返ってきます。

jsonp ( {
“message”: null, “results”: [ { “address1”: “高知県”, “address2”: “南国市”, “address3”: “蛍が丘”, “kana1”: “コウチケン”, “kana2”: “ナンコクシ”, “kana3”: “ホタルガオカ”, “prefcode”: “39”, “zipcode”: “7830060” } ], “status”: 200
})

この中で青字になっている部分がJSON形式のデータです。
Javascriptでは連想配列として扱えますね。

そして赤字がコールしてもらう関数名で任意に指定できます。
指定方法はAPIの読み出しURLに “callback=任意の関数名” を追加します。

ここで、呼び出す側 (今回の場合は郵便番号から住所を変換するHTMLファイル) に先ほど決めた関数名の関数を定義して引数を必要な変数に代入させれば自由にデータを使用できます。

Javascriptからの利用方法

ではどうやって利用するのか具体的に示します。

HTMLは基本的にコードの上から順に実行されます。
なので、先にJSONPで呼び出させる関数を定義しておきます。

この時に注意するのは、グローバル関数にすることです。
クロージャ (関数内の関数や全体を “(function(){ *** })();” ) に入れてはいけません。

<!-- 呼び出される関数の定義 -->
<script>
// この関数は外部ファイルにすると読み込まれる順番が前後する可能性があるので必ず直接書き込むこと
var jsonp = function( $data ){
	// $data を普通の連想配列として扱える
};
// もちろん function で定義してもOK (Javascript的には全く同じに関数定義されます)
function jsonp( $data ){
	// $data を普通の連想配列として扱える
}
</script>
<!-- JSONPの読み出し -->
<script src="http://zipcloud.ibsnet.co.jp/api/search?zipcode=7830060&callback=jsonp"></script>

ユーザの入力を待って読み込む

では、本題です。
上の方法だとはじめから決まったデータしか受信することができません。

なので、ページが読み込まれてからユーザの入力した情報を使って読み込む方法が必要です。

これもそれほど難しくはなく、ユーザの入力後にsrcipt要素を追加すれば良いです。
DOM操作ではおなじみの “appendChild” と “removeChild” メソッドを活用します。

HTML側には “onchange” 属性で内容が更新されたら実行されるようにします。

<!-- 呼び出される関数の定義 -->
<script>
var requestJSONP = function( $request ){
	// body要素かhead要素にscript要素を追加します
	// 追加した要素は "_API" の変数名で操作できるように代入しておきます
	var _API = document.body.appendChild(document.createElement("script"));
	// 任意のJSONPのURLに必要な情報が追加されるようにしてscript要素に読み出させます
		_API.src = "APIのURL?key=" + $request + "&callback=jsonp";
	// 読み込み成功と失敗で処理を変える場合以下
	// _API.onload = fucntion(){ /*成功時の処理*/ };
	// _API.onerror = fucntion(){ /*失敗時の処理*/ };
	// 不要になった要素を削除して終了
	document.body.removeChild(_API);
};
</script>

<!-- onchange属性で入力欄の内容が変更されたらrequestJSONP関数を入力内容を引数にして呼び出すように指定します -->
<!-- 別にボタンを用意してonclick属性で指定しても良いと思います -->
<input size="20" type="text" name="zipcode" maxlength="9" type="tel" onchange="javascript:requestJSONP(this.value)">

まとめ

以上、ZipCloudを用いた郵便番号から住所を自動入力させる方法でした。

ちなみにですが、このAPIが非常に良くできていて住所の区切り文字であるハイフンは無視されるようになっていますのでJavascript側ではそのあたりの処理が不要になっています。
また、データベースに無い郵便番号が入力された場合は結果の値がnullで帰ってくるので失敗した時の処理を割愛しても問題なく活用できます。
(messageには住所が見つからない旨、statusにも失敗の400が入ります)

どなたかのお役に立てれば幸いです。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)