Geocoding API v4 memperkenalkan beberapa metode baru yang menggantikan fungsi di API v3. Panduan ini menunjukkan cara memigrasikan aplikasi Anda untuk menggunakan metode v4 baru.
Anda dapat menggunakan kunci API yang ada dengan metode v4 baru. Namun, jika Anda telah meminta peningkatan kuota pada API v3, Anda harus meminta peningkatan pada API v4 baru.
Bermigrasi dari Geocoding Forward v3
Jika Anda menggunakan Geocoding v3 untuk melakukan geocoding pada alamat, Anda harus bermigrasi ke metode Geocode an address v4, yang menerima permintaan GET.
API v4 mengubah nama, struktur, dan dukungan untuk beberapa parameter. Sebaiknya Anda menggunakan mask kolom untuk menentukan kolom yang ingin ditampilkan dalam respons.
Meminta perubahan parameter
| Parameter v3 | Parameter v4 | Catatan |
|---|---|---|
address, components |
address |
Alamat tidak terstruktur (v3 address) kini diteruskan di jalur URL. Komponen alamat terstruktur (components v3) dapat diteruskan sebagai parameter kueri address.*. Lihat Mereproduksi filter komponen v3. |
bounds |
locationBias.rectangle |
Diganti namanya; struktur diubah menjadi objek. |
language |
languageCode |
Nama telah diganti. Jika dihilangkan, v3 akan menggunakan header Accept-Language atau ditetapkan secara default ke en, sedangkan v4 ditetapkan secara default ke bahasa dan skrip lokal lokasi. |
region |
regionCode |
Nama telah diganti. Jika dihilangkan, v3 akan ditetapkan secara default ke us, sedangkan v4 tidak memiliki nilai default. |
extra_computations |
Dihapus | Diganti dengan metode SearchDestinations. |
Perubahan kolom respons
| Kolom v3 | Kolom v4 | Catatan |
|---|---|---|
status, error_message |
Dihapus | v4 menggunakan kode status HTTP dan isi error. |
results.address_components.long_name / results.address_components.short_name |
results.addressComponents.longText / results.addressComponents.shortText |
Nama telah diganti. |
results.geometry.location_type |
results.granularity |
Nama telah diganti. |
results.geometry.location |
results.location |
Nama kolom: lat/lng -> latitude/longitude. |
results.geometry.viewport |
results.viewport |
Nama kolom: northeast/southwest -> high/low. |
results.postcode_localities |
results.postalCodeLocalities |
Nama telah diganti. Kini ditampilkan untuk satu atau beberapa lokalitas (v3 memerlukan >1). |
results.partial_match |
Dihapus | |
| Baru | results.addressComponents.languageCode |
Bahasa komponen alamat tertentu. |
| Baru | results.bounds |
Batas eksplisit menggunakan high/low. |
| Baru | results.place |
Nama resource untuk tempat. |
| Baru | results.postalAddress |
Objek PostalAddress terstruktur. |
Mereproduksi filter komponen v3
Geocoding Forward di Geocoding v3 menyertakan parameter components yang memungkinkan
pemfilteran ketat hasil untuk komponen tertentu (misalnya,
components=country:US). Geocoding Forward di v4 tidak mendukung jenis
pemfilteran ketat ini dalam parameter permintaan. Di v4, Anda dapat memberikan informasi alamat sebagai satu string tidak terstruktur di jalur atau sebagai parameter kueri terstruktur seperti address.addressLines, address.locality, address.administrativeArea, address.postalCode, dan address.regionCode.
Parameter terstruktur tidak berfungsi sebagai filter ketat. Sebagai gantinya, semua komponen yang disediakan digabungkan untuk membentuk alamat lengkap yang akan dicoba di-geocoding oleh API. API akan menelusuri kecocokan terbaik untuk seluruh alamat yang ditentukan di semua komponen. Menyediakan komponen secara terstruktur dapat membantu API
memahami intent dengan lebih baik, terutama saat informasi alamat
dikumpulkan dari kolom formulir yang terpisah. Hal ini dapat membantu API dalam menangani kesalahan ketik kecil atau ambiguitas dalam setiap komponen, karena jenis informasi di setiap kolom sudah jelas.
Untuk mencapai perilaku yang mirip dengan filter komponen ketat v3, Anda harus menerapkan
pemfilteran sisi klien pada array results yang ditampilkan oleh API v4 berdasarkan
objek postalAddress dan addressComponents dalam respons.
Tabel berikut menunjukkan kecocokan terbaik antara filter components v3 dan
kolom postalAddress v4:
| filter komponen v3 | Kolom respons v4 |
|---|---|
country |
postalAddress.regionCode |
postal_code |
postalAddress.postalCode |
administrative_area |
postalAddress.administrativeArea atau addressComponents |
Contoh pemfilteran sisi klien
Contoh berikut menunjukkan cara memfilter hasil untuk mencapai perilaku yang mirip dengan pemfilteran komponen v3 untuk kolom yang didukung: negara, wilayah administratif, dan kode pos. Sebaiknya jangan memfilter kolom lain karena tidak ada kriteria pemfilteran yang andal.
Filter menurut Negara
Cocokkan address.regionCode dari permintaan Anda dengan postalAddress.regionCode di setiap hasil. Perhatikan bahwa meskipun API menerima kode wilayah huruf kecil dalam permintaan, API selalu menampilkan kode wilayah dalam huruf besar dalam respons, sehingga Anda harus menormalisasi input ke huruf besar sebelum melakukan perbandingan.
Contoh Kode Python
def filter_by_country(results, region_code): return [ res for res in results if res.get('postalAddress', {}).get('regionCode') == region_code.upper() ] # Example usage: # v4_response = ... # API call response # filtered = filter_by_country(v4_response.get('results', []), 'US')
Contoh Kode Node.js
function filterByCountry(results, regionCode) { return results.filter(res => res.postalAddress?.regionCode === regionCode.toUpperCase()); } // Example usage: // const v4Response = ... # API call response // const filtered = filterByCountry(v4Response.results, 'US');
Filter menurut Wilayah Administratif
Cocokkan address.administrativeArea dari permintaan Anda dengan postalAddress.administrativeArea di setiap hasil. Sama seperti kode negara, Anda harus menormalisasi input menjadi huruf besar sebelum melakukan perbandingan. Hal ini hanya dapat diandalkan jika administrativeArea dalam permintaan Anda diberikan dengan singkatan 2 huruf standar. postalAddress.administrativeArea dalam respons mungkin tidak cocok secara langsung dengan akhiran kode ISO 3166-2 karena beberapa alasan. Pertama, di beberapa area, subdivisi yang sesuai dengan kode ISO 3166-2 bukan bagian dari representasi standar alamat pos. Misalnya, di Spanyol, wilayah administratif level 1 (misalnya, "CN" untuk Canarias) mungkin ada di addressComponents, tetapi postalAddress.administrativeArea mungkin berisi area level 2 (misalnya, "Santa Cruz de Tenerife"). Kedua, di beberapa area, singkatan subdivisi
tidak umum digunakan dan diwakili di postalAddress.administrativeArea
dengan nama yang lebih panjang (untuk alasan serupa, addressComponents.shortText untuk komponen alamat
yang sesuai dengan subdivisi mungkin tidak cocok dengan akhiran kode ISO 3166-2 subdivisi). Selain itu, subdivisi dalam beberapa kasus dapat direpresentasikan di komponen alamat untuk administrative_area_level_n dengan n lebih besar dari 1.
Untuk mendapatkan hasil yang paling komprehensif, Anda harus memeriksa kecocokan di postalAddress.administrativeArea dan addressComponents apa pun dengan jenis administrative_area_level_n (misalnya, administrative_area_level_1).
Contoh Kode Python
def filter_by_admin_area(results, admin_area): target = admin_area.upper() filtered = [] for res in results: # Check postalAddress pa_aa = res.get('postalAddress', {}).get('administrativeArea', '') if pa_aa == target: filtered.append(res) continue # Check all administrative area levels in addressComponents for comp in res.get('addressComponents', []): is_admin_level = any(t.startswith('administrative_area_level_') for t in comp.get('types', [])) if is_admin_level: short = comp.get('shortText', '') if short == target: filtered.append(res) break return filtered # Example usage: # filtered = filter_by_admin_area(v4_response.get('results', []), 'CA')
Contoh Kode Node.js
function filterByAdminArea(results, adminArea) { const target = adminArea.toUpperCase(); return results.filter(res => { // Check postalAddress.administrativeArea if (res.postalAddress?.administrativeArea === target) { return true; } // Check addressComponents for any administrative area level return res.addressComponents?.some(c => { const isAdmin = c.types?.some(t => t.startsWith('administrative_area_level_')); return isAdmin && c.shortText === target; }); }); } // Example usage: // const filtered = filterByAdminArea(v4Response.results, 'CA');
Filter menurut Kode Pos
Cocokkan address.postalCode dari permintaan Anda dengan postalAddress.postalCode di setiap hasil. Anda harus menormalisasi kode pos input dan hasil sebelum perbandingan. Logika normalisasi sangat bergantung pada wilayah. Pendekatan dasar melibatkan penghapusan spasi dan tanda hubung serta konversi ke huruf yang konsisten.
Normalisasi yang lebih lanjut mungkin diperlukan untuk menangani awalan kode pos (misalnya, "L2" di Inggris Raya) atau akhiran (misalnya, "+4" di kode pos AS). Logika normalisasi spesifik yang diperlukan akan bervariasi bergantung pada negara dan format kode pos yang terlibat. Anda mungkin perlu menyesuaikan fungsi normalisasi yang disediakan atau menerapkan logika yang lebih canggih untuk wilayah yang Anda targetkan.
Contoh yang diberikan menangani kode pos AS dan memungkinkan pencocokan pada basis 5 digit meskipun ZIP+4 diberikan atau ditampilkan.
Contoh Kode Python (berfokus pada Kode Pos AS)
import re def normalize_postal_code_us(pc): # Basic normalization for US: uppercase, alphanumeric only if not pc: return "" normalized = re.sub(r'[^A-Z0-9]', '', pc.upper()) # Return only the first 5 digits for US ZIP codes return normalized[:5] def filter_by_postal_code_us(results, postal_code): normalized_input = normalize_postal_code_us(postal_code) if not normalized_input: return [] filtered_results = [] for res in results: pa_pc = res.get('postalAddress', {}).get('postalCode', '') if normalize_postal_code_us(pa_pc) == normalized_input: filtered_results.append(res) return filtered_results # Example usage: # Matches '94043', '94043-1351', '940431351' # filtered = filter_by_postal_code_us(v4_response.get('results', []), '94043') # filtered = filter_by_postal_code_us(v4_response.get('results', []), '94043-1234')
Contoh Kode Node.js (berfokus pada Kode Pos AS)
function normalizePostalCodeUs(pc) { // Basic normalization for US: uppercase, alphanumeric only const normalized = (pc || '').toUpperCase().replace(/[^A-Z0-9]/g, ''); // Return only the first 5 digits for US ZIP codes return normalized.substring(0, 5); } function filterByPostalCodeUs(results, postalCode) { const normalizedInput = normalizePostalCodeUs(postalCode); if (!normalizedInput) { return []; } return results.filter(res => { const paPc = res.postalAddress?.postalCode || ''; return normalizePostalCodeUs(paPc) === normalizedInput; }); } // Example usage: // Matches '94043', '94043-1351', '940431351' // const filtered = filterByPostalCodeUs(v4Response.results, '94043'); // const filtered = filterByPostalCodeUs(v4Response.results, '94043-1234');
Bermigrasi dari Geocoding Terbalik v3
Jika Anda menggunakan Geocoding Terbalik v3 untuk mengubah koordinat menjadi alamat, Anda harus bermigrasi ke metode Geocoding terbalik lokasi v4, yang menerima permintaan GET.
API v4 mengubah nama, struktur, dan dukungan untuk beberapa parameter. Sebaiknya Anda menggunakan mask kolom untuk menentukan kolom yang ingin ditampilkan dalam respons.
Meminta perubahan parameter
| Parameter v3 | Parameter v4 | Catatan |
|---|---|---|
language |
languageCode |
Nama telah diganti. Jika dihilangkan, v3 akan menggunakan header Accept-Language atau ditetapkan secara default ke en, sedangkan v4 ditetapkan secara default ke bahasa dan skrip lokal lokasi. |
region |
regionCode |
Nama telah diganti. Jika dihilangkan, v3 akan ditetapkan secara default ke us, sedangkan v4 tidak memiliki nilai default. |
result_type |
types |
Diganti namanya; menggunakan parameter kueri berulang. |
location_type |
granularity |
Diganti namanya; menggunakan parameter kueri berulang. |
extra_computations |
Dihapus | Diganti dengan metode SearchDestinations. |
Perubahan kolom respons
| Kolom v3 | Kolom v4 | Catatan |
|---|---|---|
status, error_message |
Dihapus | v4 menggunakan kode status HTTP dan isi error. |
results.address_components.long_name / results.address_components.short_name |
results.addressComponents.longText / results.addressComponents.shortText |
Nama telah diganti. |
results.geometry.location_type |
results.granularity |
Nama telah diganti. |
results.geometry.location |
results.location |
Nama kolom: lat/lng -> latitude/longitude. |
results.geometry.viewport |
results.viewport |
Nama kolom: northeast/southwest -> high/low. |
| Baru | results.addressComponents.languageCode |
Bahasa komponen alamat tertentu. |
| Baru | results.bounds |
Batas eksplisit menggunakan high/low. |
| Baru | results.place |
Nama resource untuk tempat. |
| Baru | results.postalAddress |
Objek PostalAddress terstruktur. |
Bermigrasi dari Deskripsi alamat v3
Di Geocoding API v3, meneruskan extra_computations=ADDRESS_DESCRIPTORS akan menampilkan objek address_descriptor yang berisi landmarks[] dan areas[]. Di Geocoding API v4, kemampuan ini digantikan oleh metode SearchDestinations (POST /v4/geocode/destinations), yang menampilkan konteks spasial lengkap langsung dalam setiap objek Destination.
Tabel berikut memetakan kolom address_descriptor v3 lama ke kolom SearchDestinations v4 yang setara:
Kolom address_descriptor v3 |
Kolom SearchDestinations v4 |
Catatan Migrasi |
|---|---|---|
landmarks[] |
destinations[].landmarks[] |
Minta destinations.landmarks di X-Goog-FieldMask Anda. |
landmarks[].place_id |
landmarks[].place.placeId |
Digabungkan di dalam objek place (PlaceView). |
landmarks[].display_name |
landmarks[].place.displayName |
Teks yang dilokalkan (text dan languageCode). |
landmarks[].types |
landmarks[].place.types |
Array string jenis tempat. |
landmarks[].spatial_relationship |
landmarks[].relationalDescription |
Alih-alih enum mentah (ACROSS_THE_ROAD, AROUND_THE_CORNER), v4 menampilkan frasa yang dilokalkan dan dapat dibaca manusia (misalnya, "Across from Central Park"). |
landmarks[].straight_line_distance_meters |
landmarks[].straightLineDistanceMeters |
Diganti namanya menjadi lower camelCase. |
landmarks[].travel_distance_meters |
landmarks[].travelDistanceMeters |
Diganti namanya menjadi camelCase huruf kecil. |
areas[] (enum containment) |
destinations[].containingPlaces[] & subDestinations[] |
Setara terdekat yang tersedia untuk hierarki struktural: kompleks, kampus, mal, dan bangunan yang mencakup ditampilkan sebagai objek PlaceView terstruktur di containingPlaces[] dan subDestinations[] (dengan structureType ditetapkan ke GROUNDS atau BUILDING dan garis batas displayPolygon opsional). Perhatikan bahwa tidak ada pengganti langsung 1:1 untuk area kedekatan lingkungan/distrik atau enum containment v3 (NEAR, WITHIN, OUTSKIRTS). |
Bermigrasi dari geocoding Tempat v3
Jika Anda menggunakan place_id untuk mendapatkan alamat untuk ID Tempat tertentu dengan Geocoding v3, Anda harus bermigrasi ke metode Place Geocoding v4, yang menerima permintaan GET.
API v4 mengubah nama, struktur, dan dukungan untuk beberapa parameter. Sebaiknya Anda menggunakan mask kolom untuk menentukan kolom yang ingin ditampilkan dalam respons.
Meminta perubahan parameter
| Parameter v3 | Parameter v4 | Catatan |
|---|---|---|
place_id |
Kolom place dalam proto permintaan |
ID Tempat kini disediakan sebagai parameter jalur places/{place}, misalnya: https://geocode.googleapis.com/v4/geocode/places/ChIJj61dQgK6j4AR4GeTYWZsKWw. Ini dipetakan ke kolom tempat dalam permintaan yang mendasarinya. |
language |
languageCode |
Nama telah diganti. Jika dihilangkan, v3 akan menggunakan header Accept-Language atau ditetapkan secara default ke en, sedangkan v4 ditetapkan secara default ke bahasa dan skrip lokal lokasi. |
region |
regionCode |
Nama telah diganti. Jika dihilangkan, v3 akan ditetapkan secara default ke us, sedangkan v4 tidak memiliki nilai default. |
Perubahan kolom respons
| Kolom v3 | Kolom v4 | Catatan |
|---|---|---|
status, error_message |
Dihapus | v4 menggunakan kode status HTTP dan isi error. |
results |
(root) | v4 menampilkan satu objek hasil, bukan array results. |
results.address_components.long_name / results.address_components.short_name |
addressComponents.longText / addressComponents.shortText |
Nama telah diganti. |
results.geometry.location_type |
granularity |
Nama telah diganti. |
results.geometry.location |
location |
Nama kolom: lat/lng -> latitude/longitude. |
results.geometry.viewport |
viewport |
Nama kolom: northeast/southwest -> high/low. |
results.postcode_localities |
postalCodeLocalities |
Nama telah diganti. Kini ditampilkan untuk satu atau beberapa lokalitas (v3 memerlukan >1). |
| Baru | addressComponents.languageCode |
Bahasa komponen alamat tertentu. |
| Baru | bounds |
Batas eksplisit menggunakan high/low. |
| Baru | place |
Nama resource untuk tempat. |
| Baru | postalAddress |
Objek PostalAddress terstruktur. |
Bermigrasi dari Geocoding Hyperlocal Data ke Destinations
Fitur berikut di Geocoding API v3 digantikan oleh metode SearchDestinations Geocoding API v4:
- Masuk
- Titik navigasi
- Garis batas bangunan
- Area
Jika Anda menggunakan Geocoding API v3 untuk fitur di atas, gunakan dokumen ini
untuk membantu Anda menggunakan metode SearchDestinations sebagai gantinya untuk mendapatkan fitur ini.
Dokumen ini menjelaskan tempat menemukan fitur ini dalam respons SearchDestinations, serta perbedaan cara fitur ini direpresentasikan dalam respons API antara Geocoding API v3 dan metode SearchDestinations Geocoding API v4.
Masuk
Untuk mendapatkan pintu masuk yang terkait dengan
destination,
gunakan kolom destination.entrances.
Setiap entrance
di destination.entrances memiliki kolom berikut (menggantikan skema buildings.entrances v3 lama):
displayName- kolom opsional baru yang berisi nama yang dapat dibaca manusia untuk pintu masuk, misalnya"Gate B".location- lokasi jenisLatLngmenggunakanlatitudedanlongitude(menggantikanlat/lngv3).tags- sama dengan kolomtagsdari pintu masuk Geocoding API v3 (sepertiPREFERRED).place- nama resource tempat (misalnya,places/ChIJ...), menggantikan kolombuilding_place_iddari Geocoding API v3. Di v4, tempat ini dapat merepresentasikan struktur tujuan apa pun (bangunan, kampus, atau taman), bukan hanya bangunan.
Titik navigasi
Untuk mendapatkan titik navigasi yang terkait dengan destination, gunakan kolom
destination.navigationPoints.
Setiap navigationPoint
di destination.navigationPoints memiliki kolom berikut (menggantikan skema navigation_points v3 lama):
navigationPointToken- string token terenkripsi yang digunakan untuk merutekan ke titik navigasi spesifik ini dalam metodeComputeRoutesRoutes API (Waypoint.navigationPointToken). Lihat Merutekan menggunakan token titik navigasi.displayName- kolom opsional baru yang berisi nama yang dapat dibaca manusia untuk titik navigasi, misalnya"5th Ave".location- lokasi jenisLatLngmenggunakanlatitudedanlongitude.travelModes- mirip dengan kolomrestricted_travel_modesdari Geocoding API v3, kecuali bahwa v4 menentukan mode perjalanan yang dapat diterima (DRIVE,WALK), bukan mode perjalanan yang dibatasi.usage- kolom baru yang menentukan kasus penggunaan kedatangan yang didukung untuk titik navigasi (sepertiPICKUP,DROPOFF, atauPARKING).
Garis batas bangunan
Untuk mendapatkan garis batas bangunan yang terkait dengan destination, gunakan kolom displayPolygon dari objek placeView di destination yang merepresentasikan bangunan (menggantikan array buildings.building_outlines v3 lama). Untuk setiap placeView, periksa apakah itu adalah bangunan dengan kolom
placeView.structureType. Jika jenis strukturnya adalah BUILDING, Anda bisa mendapatkan kerangka dari
kolom placeView.displayPolygon. placeView juga akan memiliki kolom tambahan
untuk bangunan yang tidak ada di Geocoding API v3.
destination dapat memiliki objek placeView yang mewakili bangunan di
kolom berikut:
destination.primary- tempat utama untuk tujuan.destination.containingPlaces- kolom berulang yang menyimpan tempat yang lebih besar yang "berisi" tempat utama. Misalnya, jika tempat utama adalahsubpremise,containingPlacesbiasanya menyimpanplaceViewyang mewakili bangunan.destination.subDestinations- kolom berulang yang menyimpan sub-tujuan dari tempat utama (misalnya, unit apartemen atau suite individual dalam sebuah bangunan).
Perhatikan bahwa format placeView.displayPolygon cocok dengan format garis batas bangunan di Geocoding API v3, yang merupakan format GeoJSON, menggunakan format RFC 7946.
Area
Serupa dengan garis batas bangunan, untuk mendapatkan halaman yang terkait dengan
destination, gunakan kolom displayPolygon dari objek placeView
di destination yang mewakili halaman (menggantikan array grounds v3 lama). Untuk setiap placeView, periksa apakah poligon tersebut adalah poligon tanah dengan kolom placeView.structureType. Jika
jenis strukturnya adalah GROUNDS, Anda bisa mendapatkan struktur dari
kolom placeView.displayPolygon. placeView juga akan memiliki kolom tambahan untuk dasar yang tidak ada di Geocoding API v3.
destination dapat memiliki objek placeView yang mewakili halaman di
kolom berikut:
destination.primarydestination.containingPlacesdestination.subDestinations
Perhatikan bahwa format placeView.displayPolygon cocok dengan format batas lahan di Geocoding API v3, yang merupakan format GeoJSON, menggunakan format RFC 7946.
Presisi hasil
Di Geocoding API v3, kolom location_type dalam geometri respons menunjukkan presisi hasil, dan beberapa klien akan memberi peringkat atau memfilter hasil berdasarkan nilai ini (ROOFTOP, RANGE_INTERPOLATED, GEOMETRIC_CENTER, dan APPROXIMATE). Dalam migrasi Geocoding API v4 standar, kolom ini diganti namanya menjadi granularity.
Di Destinations API (SearchDestinations v4), tidak ada kolom location_type. Sebagai gantinya, informasi spasial ditangani secara berbeda:
- Tidak memerlukan pemfilteran sisi klien manual: Meskipun Geocoding standar
memberikan beberapa hasil di berbagai tingkat perincian, metode
SearchDestinationsmeminimalkan ambiguitas dengan me-resolve ke satu tujuan yang dioptimalkan jika memungkinkan. Hal ini menghilangkan kebutuhan klien untuk memfilter menurut jenis lokasi guna menentukan hasil terbaik. - Informasi spasial yang diwakili oleh jenis struktur dan poligon tampilan:
Geometri dan struktur spasial ditunjukkan oleh:
displayPolygon(untuk geometri yang tepat).- Kolom
structureTypedalam objekplaceView.
- Pemetaan jenis struktur:
structureTypedariPOINT,BUILDING, atauSECTIONumumnya sesuai dengan yang sebelumnya disebutROOFTOP.structureTypedariGROUNDSumumnya sesuai denganGEOMETRIC_CENTER.
Menggunakan mask kolom untuk meminta fitur ini
Metode SearchDestinations
memerlukan mask kolom, seperti yang dijelaskan dalam Memilih kolom yang akan
ditampilkan. Masker kolom dapat ditetapkan ke * untuk menampilkan semua kolom, atau Anda dapat menetapkannya ke kolom tertentu yang ingin Anda terima. Misalnya, permintaan API berikut menetapkan mask kolom
untuk menerima semua kolom yang diperlukan guna mendapatkan pintu masuk, titik navigasi, garis batas
bangunan, dan halaman tujuan:
curl -X POST -d '{"place": "places/ChIJG3kh4hq6j4AR_XuFQnV0_t8"}' \
-H "X-Goog-Api-Key: API_KEY" \
-H "Content-Type: application/json" \
-H "X-Goog-FieldMask: destinations.entrances,destinations.navigationPoints,destinations.primary,destinations.containingPlaces,destinations.subDestinations" \
https://geocode.googleapis.com/v4/geocode/destinations
Resep Migrasi & Pola Kode Umum
Saat memigrasikan alur kerja yang kompleks dari Geocoding v3 atau Geocoding++ ke SearchDestinations, gunakan resep kode berikut untuk mengekstrak struktur spasial dan alamat umum.
Mengekstrak poligon bangunan terbaik
Jika Anda ingin merender batas gedung untuk lokasi atau tujuan:
- Periksa apakah tempat
primarymemilikistructureType === 'BUILDING'dan berisidisplayPolygon. - Jika tidak, periksa
containingPlacesuntuk menemukan bangunan yang mengelilinginya (berguna jika tujuan utama adalah subtujuan dari bangunan yang lebih besar). - Jika tidak ada bangunan yang mencakup, periksa
subDestinationsuntuk melihat apakah bangunan individual tercantum.
Contoh Kode Python
def get_best_building_polygon(destination): primary = destination.get('primary', {}) if primary.get('structureType') == 'BUILDING' and 'displayPolygon' in primary: return primary['displayPolygon'] # Check containing places for the parent building for place in destination.get('containingPlaces', []): if place.get('structureType') == 'BUILDING' and 'displayPolygon' in place: return place['displayPolygon'] # Fallback to sub-destinations if available for place in destination.get('subDestinations', []): if place.get('structureType') == 'BUILDING' and 'displayPolygon' in place: return place['displayPolygon'] return None
Contoh Kode Node.js
function getBestBuildingPolygon(destination) { const { primary = {}, containingPlaces = [], subDestinations = [] } = destination; if (primary.structureType === 'BUILDING' && primary.displayPolygon) { return primary.displayPolygon; } const parentBuilding = containingPlaces.find( p => p.structureType === 'BUILDING' && p.displayPolygon ); if (parentBuilding) { return parentBuilding.displayPolygon; } const subBuilding = subDestinations.find( p => p.structureType === 'BUILDING' && p.displayPolygon ); return subBuilding?.displayPolygon || null; }
Mengekstrak garis batas tanah
Jika Anda memerlukan batas kompleks apartemen, kampus perusahaan, pusat perbelanjaan, atau taman:
- Jika tempat
primarymewakili seluruh kompleks (structureType === 'GROUNDS'), gunakanprimary.displayPolygon. - Jika tempat
primaryadalah bangunan atau pintu masuk yang terletak di dalam kompleks yang lebih besar, temukan area yang mengelilinginya dicontainingPlaces.
Contoh Kode Python
def get_grounds_polygon(destination): primary = destination.get('primary', {}) if primary.get('structureType') == 'GROUNDS' and 'displayPolygon' in primary: return primary['displayPolygon'] for place in destination.get('containingPlaces', []): if place.get('structureType') == 'GROUNDS' and 'displayPolygon' in place: return place['displayPolygon'] return None
Contoh Kode Node.js
function getGroundsPolygon(destination) { const { primary = {}, containingPlaces = [] } = destination; if (primary.structureType === 'GROUNDS' && primary.displayPolygon) { return primary.displayPolygon; } const groundsPlace = containingPlaces.find( p => p.structureType === 'GROUNDS' && p.displayPolygon ); return groundsPlace?.displayPolygon || null; }
Memilih tempat terkenal untuk tampilan alamat versus kedatangan jarak dekat
Geocoding v3 address_descriptor menampilkan enum spatial_relationship (WITHIN, BESIDE, BEHIND, NEAR, ACROSS_THE_ROAD, AROUND_THE_CORNER). Di SearchDestinations:
- Tidak ada enum hubungan mentah. Sebagai gantinya, gunakan
relationalDescription.textsecara langsung. File ini berisi frasa yang dilokalkan dan siap ditampilkan seperti"Across from Central Park"atau"Behind the convention center". Jangan tambahkan"Near "secara manual. - Gunakan
tagsuntuk memilih tempat terkenal yang tepat untuk kasus penggunaan Anda:ARRIVAL: Tempat terkenal hiperlokal yang terletak tepat di samping, menghadap, atau di seberang jalan dari tujuan (biasanya dalam jarak 50–100 meter). Paling cocok untuk kedatangan pengemudi secara real-time, konfirmasi pengiriman kurir, atau kartu kedatangan dalam aplikasi.ADDRESS: Tempat terkenal di sekitar (biasanya dalam jarak 100–500 meter). Paling cocok untuk checkout yang ditampilkan kepada pelanggan, peninjauan pesanan, atau disambiguasi tujuan sebelum perjalanan.- Jika tempat terkenal memiliki tag
ADDRESSdanARRIVAL, tempat tersebut terkenal di lingkungan sekitar dan berada tepat di samping tujuan.
Contoh Kode Python
def get_best_relational_landmark(destination, is_last_mile=True): """Select the best landmark based on user context. Args: destination: Destination object from SearchDestinations. is_last_mile: True for arrival and delivery guidance (prefers ARRIVAL tags). False for address display and disambiguation (prefers ADDRESS tags). Returns: Dict with landmark description, distances, tags, and placeId, or None. """ landmarks = destination.get('landmarks', []) if not landmarks: return None target_tag = 'ARRIVAL' if is_last_mile else 'ADDRESS' # Landmarks are ranked by relevance and proximity. Select the first candidate matching the target tag. for lm in landmarks: tags = lm.get('tags', []) if target_tag in tags or ('ARRIVAL' in tags and 'ADDRESS' in tags): description = lm.get('relationalDescription', {}).get('text') if description: return { 'description': description, 'travelDistanceMeters': lm.get('travelDistanceMeters'), 'straightLineDistanceMeters': lm.get('straightLineDistanceMeters'), 'tags': tags, 'placeId': lm.get('place', {}).get('placeId') } # Fallback to the first available landmark with a relational description if no tagged match is found for lm in landmarks: description = lm.get('relationalDescription', {}).get('text') if description: return { 'description': description, 'travelDistanceMeters': lm.get('travelDistanceMeters'), 'straightLineDistanceMeters': lm.get('straightLineDistanceMeters'), 'tags': lm.get('tags', []), 'placeId': lm.get('place', {}).get('placeId') } return None
Contoh Kode Node.js
/** * Select the best landmark based on user context. * * @param {Object} destination Destination object from SearchDestinations. * @param {boolean} [isLastMile=true] True for arrival and delivery guidance * (prefers ARRIVAL tags). False for address display and disambiguation * (prefers ADDRESS tags). * @return {Object|null} */ function getBestRelationalLandmark(destination, isLastMile = true) { const landmarks = destination.landmarks || []; if (!landmarks.length) return null; const targetTag = isLastMile ? 'ARRIVAL' : 'ADDRESS'; // Landmarks are ranked by relevance and proximity. Select the first candidate matching the target tag. const match = landmarks.find((lm) => { const tags = lm.tags || []; return (tags.includes(targetTag) || (tags.includes('ARRIVAL') && tags.includes('ADDRESS'))) && lm.relationalDescription?.text; }) || landmarks.find((lm) => lm.relationalDescription?.text); if (match) { return { description: match.relationalDescription.text, travelDistanceMeters: match.travelDistanceMeters, straightLineDistanceMeters: match.straightLineDistanceMeters, tags: match.tags || [], placeId: match.place?.placeId || null, }; } return null; }
Menentukan rute ke titik navigasi kendaraan dan pintu masuk pilihan
Alur kerja pengiriman dan kedatangan jarak jauh menggabungkan dua jenis titik akses spasial yang saling melengkapi:
- Mengemudi belokan demi belokan: Mengarahkan kendaraan ke titik penurunan di jalan yang ditentukan menggunakan
navigationPoints. Titik navigasi diberi peringkat terlebih dahulu berdasarkan kedekatan dan relevansi, sehingga kandidat pertama dengan mode perjalanan yang Anda inginkan (seperti'DRIVE') dan tag penggunaan (seperti'DROPOFF'atau'PICKUP') memberikan titik jalan kendaraan yang optimal. KirimnavigationPointToken-nya ke metodeComputeRoutesRoutes API (Waypoint.navigationPointToken) atau Navigation SDK. Jika tidak ada titik mengemudi yang disesuaikan dengan jalan, gunakan pintu masuk bangunan atau centroid utama. - Akses pintu fisik: Pandu kurir yang berjalan kaki atau penumpang ke pintu masuk gedung menggunakan
destinations.entrances. Periksatagsuntuk'PREFERRED'guna menemukan pintu masuk yang kemungkinan menyediakan akses fisik langsung. Jika tidak ada data pintu masuk, gunakan titik navigasi pejalan kaki (travelModestermasuk'WALK') atau centroid utama.
Contoh Kode Python
def get_routing_and_arrival_points(destination, usage_tag=None): navigation_points = destination.get('navigationPoints', []) entrances = destination.get('entrances', []) primary_location = destination.get('primary', {}).get('location') # 1. Doorstep / Physical Entrance # Prefer PREFERRED entrance -> any entrance -> WALK nav point -> primary location preferred_entrance = None for ent in entrances: if 'PREFERRED' in ent.get('tags', []): preferred_entrance = ent break if not preferred_entrance and entrances: preferred_entrance = entrances[0] walk_nav_point = None for np in navigation_points: if 'WALK' in np.get('travelModes', []): walk_nav_point = np break if preferred_entrance: doorstep_location = preferred_entrance.get('location') elif walk_nav_point: doorstep_location = walk_nav_point.get('location') else: doorstep_location = primary_location # 2. Vehicle Routing Waypoint # Find a driving navigation point. If usage_tag (such as 'DROPOFF' or 'PICKUP') # is specified, prioritize a candidate with that usage tag; otherwise fall back # to the first available driving point. drive_nav_point = None fallback_drive_point = None for np in navigation_points: if 'DRIVE' in np.get('travelModes', []): if usage_tag and usage_tag in np.get('usages', []): drive_nav_point = np break # Exact match for desired usage tag elif fallback_drive_point is None: fallback_drive_point = np # First driving point as fallback if not drive_nav_point: drive_nav_point = fallback_drive_point if drive_nav_point: vehicle_location = drive_nav_point.get('location') nav_token = drive_nav_point.get('navigationPointToken') elif preferred_entrance: vehicle_location = preferred_entrance.get('location') nav_token = None else: vehicle_location = primary_location nav_token = None return { 'vehicleRoutingWaypoint': { 'navigationPointToken': nav_token, 'location': vehicle_location, }, 'doorstepLocation': doorstep_location, }
Contoh Kode Node.js
function getRoutingAndArrivalPoints(destination, usageTag = null) { const navigationPoints = destination.navigationPoints || []; const entrances = destination.entrances || []; const primaryLocation = destination.primary?.location || null; // 1. Doorstep / Physical Entrance const preferredEntrance = entrances.find(ent => ent.tags?.includes('PREFERRED')) || entrances[0] || null; const walkNavPoint = navigationPoints.find(np => np.travelModes?.includes('WALK')) || null; const doorstepLocation = preferredEntrance?.location || walkNavPoint?.location || primaryLocation; // 2. Vehicle Routing Waypoint // Find a driving navigation point. If usageTag (such as 'DROPOFF' or 'PICKUP') // is specified, prioritize a candidate with that usage tag; otherwise fall back // to the first available driving point. const driveNavPoint = (usageTag && navigationPoints.find(np => np.travelModes?.includes('DRIVE') && np.usages?.includes(usageTag))) || navigationPoints.find(np => np.travelModes?.includes('DRIVE')) || null; let vehicleLocation = primaryLocation; let navToken = null; if (driveNavPoint) { vehicleLocation = driveNavPoint.location; navToken = driveNavPoint.navigationPointToken; } else if (preferredEntrance) { vehicleLocation = preferredEntrance.location; } return { vehicleRoutingWaypoint: { navigationPointToken: navToken, location: vehicleLocation, }, doorstepLocation: doorstepLocation, }; }
Pertimbangan keamanan
Geocoding API v4 dirancang sebagai API server ke server. Tidak ada jalur migrasi langsung untuk pengguna JavaScript dari v3 ke v4. Memanggil metode v4 langsung dari JavaScript sisi klien (misalnya, di browser) menggunakan kunci API akan membuat kunci API Anda berisiko tinggi dicuri dan disalahgunakan.
Pembatasan perujuk HTTP, meskipun berguna, bukanlah perlindungan yang memadai untuk endpoint layanan web karena dapat dengan mudah diabaikan oleh penyerang yang memalsukan header Referer dalam permintaan mereka.
Pendekatan yang direkomendasikan
Cara yang direkomendasikan untuk menggunakan Geocoding API v4 adalah dari server backend Anda sendiri. Aplikasi klien Anda harus membuat permintaan ke server perantara ini, yang kemudian memanggil Google API dengan aman menggunakan kunci API yang dilindungi (misalnya, kunci yang disimpan dalam variabel lingkungan atau secret manager). Hal ini memastikan bahwa kunci API Anda tidak pernah terekspos dalam kode frontend.
Alternatif untuk kebutuhan sisi klien
Jika Anda memiliki kebutuhan sisi klien yang memerlukan geocoding, pertimbangkan untuk menggunakan salah satu solusi sisi klien yang ada:
- Layanan Geocoding di Maps JavaScript API: Layanan Geocoding terus menggunakan backend v3 dan dirancang untuk digunakan di lingkungan browser.
- Kit UI Places: Gunakan Kit UI Places, termasuk elemen Place Autocomplete, untuk elemen antarmuka pengguna yang terkait dengan alamat.