便利すぎる！Google Maps APIで郵便番号から住所を取得する！サンプルそのまま使えます

## ~~2016年3月 24日に利用規約が更新されており、以下の用途での実装がNGであることがわかりました。~~

ご指摘いただきありがとうございます。2019年4月現在、問題なく利用できるようです。
https://developers.google.com/maps/documentation/geocoding/usage-limits#header_3

# Google Maps APIが便利すぎる！

Google Maps APIを利用することで下の画像のように郵便番号から住所が取得できます。
※ページの最後にそのまま使用できるサンプルを載せています。

![gif.gif](https://qiita-image-store.s3.amazonaws.com/0/83231/98980c9d-50ad-fe37-ffec-a7981a9a228f.gif)

## 経緯

[郵便番号データダウンロード](http://www.post.japanpost.jp/zipcode/download.html)からCSVをダウンロードして...  ということをしたくなかったので、郵便番号から住所情報を取得できるAPIは無いかと探していたところ、Google Maps APIがとても便利そうだったので使用してみました。

## JSONで住所情報を取得する

Google Maps APIにはAjaxでリクエストを飛ばすと、Json形式でレスポンスしてくれます。
レスポンス内容は、

https://maps.googleapis.com/maps/api/geocode/json?address=160-0002&language=ja&sensor=false
※郵便番号のハイフンはあっても無くても動作します。

```json
{
   "results" : [
      {
         "address_components" : [
            {
               "long_name" : "160-0002",
               "short_name" : "160-0002",
               "types" : [ "postal_code" ]
            },
            {
               "long_name" : "坂町",
               "short_name" : "坂町",
               "types" : [ "sublocality_level_1", "sublocality", "political" ]
            },
            {
               "long_name" : "新宿区",
               "short_name" : "新宿区",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "東京都",
               "short_name" : "東京都",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "日本",
               "short_name" : "JP",
               "types" : [ "country", "political" ]
            }
         ],
         "formatted_address" : "〒160-0002, 日本",
         "geometry" : {
            "bounds" : {
               "northeast" : {
                  "lat" : 35.692041,
                  "lng" : 139.7292123
               },
               "southwest" : {
                  "lat" : 35.688532,
                  "lng" : 139.7246218
               }
            },
            "location" : {
               "lat" : 35.6907555,
               "lng" : 139.7272033
            },
            "location_type" : "APPROXIMATE",
            "viewport" : {
               "northeast" : {
                  "lat" : 35.692041,
                  "lng" : 139.7292123
               },
               "southwest" : {
                  "lat" : 35.688532,
                  "lng" : 139.7246218
               }
            }
         },
         "place_id" : "ChIJoebNl_SMGGAR4LtICJbkh5I",
         "types" : [ "postal_code" ]
      }
   ],
   "status" : "OK"
}
```

なるほど、address_componentsに配列で国、都道府県、市区町村、番地がそれぞれ別々に入っていますね！ これは利用しやすい。国コードや緯度経度まで取得してくれていますが今回は利用しません。

## サンプルソース(そのまま使えます)

上記のAPIをAjaxで呼び出し、返却値を各入力欄に挿入しています。詳しい内容はソースコード内のコメントを参照してください。CSS付きです。
※JQueryを使用します。

```html:sample.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="css/zip.css">
</head>
<body>
  <div class="wrapper">
    <div class="content">
      <label>郵便番号</label>
      <span class="content_form">
        <input id="zip" name="zip" type="text" placeholder="1600002"/>
      </span>
      <span class="content_form">
        <input class="studentEnrollment_button" type="button" value="住所を自動で入力する" onClick="setState()" />
      </span>
    </div>
    <div class="content">
      <label>都道府県</label>
      <span class="content_form">
        <input id="state" name="state" type="text" placeholder="東京都" />
      </span>
    </div>
    <div class="content">
      <label>市区町村</label>
      <span class="content_form">
        <input id="city" name="city" type="text" placeholder="新宿区" />
      </span>
    </div>
    <div class="content">
      <label>番地</label>
      <span class="content_form">
        <input id="address1" name="address1" type="text" placeholder="西新宿666" />
      </span>
    </div>
    <div class="content">
      <label>建物名・階・部屋番号</label>
      <span class="content_form">
        <input id="address2" name="address2" type="text" placeholder="ビルヂング666" />
      </span>
    </div>
  </div>
</body>
<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
<script>
  // 郵便番号から住所を取得
  function setState() {
    var zip = $('#zip').val();

    // ここでzipのバリデーションを行ってください

    $.ajax({
      type : 'get',
      url : 'https://maps.googleapis.com/maps/api/geocode/json',
      crossDomain : true,
      dataType : 'json',
      data : {
        address : zip,
        language : 'ja',
        sensor : false
      },
      success : function(resp){
        if(resp.status == "OK"){
          // APIのレスポンスから住所情報を取得
          var obj = resp.results[0].address_components;
          if (obj.length < 5) {
            alert('正しい郵便番号を入力してください');
            return false;
          }
          //$('#country').val(obj[4]['long_name']); // 国
          $('#state').val(obj[3]['long_name']); // 都道府県
          $('#city').val(obj[2]['long_name']);  // 市区町村
          $('#address1').val(obj[1]['long_name']); // 番地
        }else{
          alert('住所情報が取得できませんでした');
          return false;
        }
      }
    });
  }
</script>
</html>
```

```css:zip.css
body{
  font-family: Helvetica ,"游ゴシック" ,"Yu Gothic" ,sans-serif;
}
.wrapper {
  margin: 0 auto;
  width: 600px;
}
.content {
  display: table;
  width: 100%;
  border-top: 1px solid #DB7093;
  border-left: 1px solid #DB7093;
  border-right: 1px solid #DB7093;
}
.content:last-child {
  border-bottom: 1px solid #DB7093;
}
.content label{
  display: table-cell;
  width: 200px;
  background-color: #DB7093;
  color: white;
  font-size: 16px;
  vertical-align: middle;
  text-indent: 1em;
}
.content .content_form {
  display: table-cell;
  padding: 10px
}
input[type="text"] {
  width: 100%;
  height: 35px;
  font-size: 18px;
  vertical-align: top;
  padding-left: 5px;
}
input[type="button"] {
  width: 100%;
  height: 40px;
  font-size: 16px;
  cursor: pointer;
  border: 1px solid gray;
  vertical-align: top;
  background-color: lightgray;
}
```

## 結果

![スクリーンショット 2016-02-23 11.51.38.png](https://qiita-image-store.s3.amazonaws.com/0/83231/a70c1594-87b7-d521-853c-f185a6b7b5c5.png)


以上になります。