こんにちは。
前回の記事では、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
のような住所を取得することができます。
今回はこのあたりで。