RailsでGoogle mapから住所データを作成する

2023/03/10

GoogleMap
Rails

こんにちは。

前回の記事では、RailsでGoogle mapの位置情報を扱うモデルを作成する方法をご紹介しました。

前回の記事はこちら

今回はより詳細に、Google mapの住所データの構造を紹介したいと思います。

住所データの構造

Google mapの住所データは、以下のような構造になっています。

ex) 郵便番号のみで検索した場合(今回の場合は「543-0044」と検索)

{"results":
  [
    {"address_components":
      [
        {
          "long_name": "543-0044",
          "short_name" : "543-0044",
          "types": [
            "postal_code"
          ]
        },
        {
          "long_name": "国分町",
          "short_name": "国分町",
          "types": [
            "political", "sublocality", "sublocality_level_2"
          ]
        },
        {
          "long_name": "天王寺区",
          "short_name": "天王寺区",
          "types": [
            "political", "sublocality", "sublocality_level_1"
          ]
        },
        {
          "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": "日本 〒543-0044",
      "geometry": {
        "bounds": {
          "northeast": {
            "lat": 34.6534706,
            "lng" : 135.5262415
          },
          "southwest": {
            "lat": 34.6500884,
            "lng": 135.5229601
          }
        },
        "location": {
          "lat": 34.6521156,
          "lng": 135.5246088
        },
        "location_type": "APPROXIMATE",
        "viewport": {
          "northeast": {
            "lat": 34.6534706,
            "lng" : 135.5262415
          },
          "southwest": {
            "lat": 34.6500884,
            "lng": 135.5229601
          }
        }
      },
      "place_id": "ChIJl-O_dP3dAGARKZHEd9h3jpE",
      "types": [ "postal_code" ]
    }
  ],
  "status" : "OK"
}

ex) 完全な住所で検索した場合(今回は「大阪府大阪市天王寺区国分町2-12」と検索)

{
  "results": [
    {
      "address_components": [
        {
          "long_name": "レジデンスハイビレッジ",
          "short_name": "レジデンスハイビレッジ"
          "types": ["premise"]
        },
        {
          "long_name": "12",
          "short_name": "12",
          "types": ["premise"]
        },
        {
          "long_name": "2",
          "short_name": "2",
          "types": ["political", "sublocality", "sublocality_level_4"]
        },
        {
          "long_name": "国分町",
          "short_name": "国分町",
          "types": ["political", "sublocality", "sublocality_level_2"]
        },
        {
          "long_name": "天王寺区",
          "short_name": "天王寺区",
          "types": ["political", "sublocality", "sublocality_level_1"]
        },
        {
          "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"]
        },
        {
          "long_name": "543-0044",
          "short_name": "543-0044",
          "types": ["postal_code"]
        }
      ],
      "formatted_address": "日本、〒543-0044 大阪府大阪市天王寺区国分町2−12 レジデンスハイビレッジ",
      "geometry": {
        "bounds": {
          "northeast": {
            "lat": 34.6525031,
            "lng": 135.5256991
          },
          "southwest": {
            "lat": 34.6523623,
            "lng": 135.5255348
          }
        },
        "location": {
          "lat": 34.6524245,
          "lng": 135.5256219
        },
        "location_type": "ROOFTOP",
        "viewport": {
          "northeast": {
            "lat": 34.6537615802915,
            "lng": 135.5269659302915
          },
          "southwest": {
            "lat": 34.6510636197085,
            "lng": 135.5242679697085
          }
        }
      },
      "place_id": "ChIJEXACjwfeAGARlxlWUjh38Ls",
      "types": ["premise"]
    }
  ],
  "status": "OK"
}

大きく異なるのは、location_typeの値です。

location_typeの値は、以下のようになっています。

  • APPROXIMATE:住所データが不完全な場合に設定されます。
  • GEOMETRIC_CENTER:住所データが完全な場合に設定されます。
  • RANGE_INTERPOLATED:住所データが不完全な場合に設定されます。
  • ROOFTOP:住所データが完全な場合に設定されます。

住所検索の場合、情報が不完全な場合は、APPROXIMATE、完全な住所情報の場合は、ROOFTOPが設定されます。

抽象度の高い(住所から建物が特定できない)住所を出す場合は、APPROXIMATEになるのでその場合のレスポンスを分岐させる必要があります。

また、細かいところでは、formatted_addressの値の、「日本」の次に「、」が入るケースと入らないケースがあります。

この原因は特定しきれていないので、今後調査しますがformatted_addressの値を使う場合は、注意が必要です。

Rubyでの加工方法

今回、formatted_addressに頼らずそれぞれの要素を取得する方法を紹介します。

厄介なところとしては、administrative_area, locality, sublocalityのような要素はlevelが複数ある場合があるので、それらをレベル順に並べるところかと思います。

今回は、administrative_area, locality, sublocalityのレベル順に並べる方法を紹介します。


# address_componentsは、上記のJSONのaddress_componentsの値を想定
def formatted_administrative_area(address_components)
  administrative_areas = address_components.select do |component|
    component[:types].any? do |type|
      type.include?('administrative_area')
    end
  end

  filtered_administrative_areas = administrative_areas.map do |area| # administrative_areaのレベル順に並べて、long_nameを取得
    { area: area[:long_name], order: area[:types].find do |type|
                                        type.include?('administrative_area_level')
                                      end.slice(-1).to_i }
  end
  # filter_administrative_areasのサンプルは以下のような形
  # [{:area=>"大阪府", :order=>1}, {:area=>"大阪市", :order=>2}]

  filtered_administrative_areas.sort_by { |h| h[:order] }.map { |h| h[:area] }.join.tr('0-9', '0-9')
end

このような感じで、administrative_area, locality, sublocalityをそれぞれレベル順に並べて、long_nameを取得することでformatted_addressのような住所を取得することができます。

今回はこのあたりで。

Related Posts

RailsでGoogle mapの位置情報を扱うモデルを作成する

RailsでGoogle mapの位置情報を扱うモデルを作成する