從 Geocoding v3 遷移至 v4

歐洲經濟區 (EEA) 開發人員

Geocoding API 第 4 版推出多項新方法,可取代 API 第 3 版的功能。本指南說明如何遷移應用程式,改用新的 v4 方法。

您可以使用現有的 API 金鑰搭配新的 v4 方法。不過,如果您已要求提高 API 第 3 版的配額,則必須要求提高新版第 4 版 API 的配額。

從 v3 正向地理編碼遷移

如果您使用 v3 地理編碼對地址進行地理編碼,請改用 v4 Geocode an address 方法,該方法接受 GET 要求。

v4 API 變更了名稱、結構和多個參數的支援。強烈建議您使用欄位遮罩,指定要在回應中傳回的欄位。

要求變更參數

v3 參數 v4 參數 附註
address、components address 非結構化地址 (v3 address) 現在會傳遞至網址路徑。結構化地址元件 (v3 components) 可以做為 address.* 查詢參數傳遞。請參閱「重現 v3 元件篩選器」。
bounds locationBias.rectangle 已重新命名;結構變更為物件。
language languageCode 已重新命名。如果省略,v3 會使用 Accept-Language 標頭或預設為 en,而 v4 則預設為地點的當地語言和文字。
region regionCode 已重新命名。如果省略,v3 會預設為 us,但 v4 沒有預設值。
extra_computations 已移除 由 SearchDestinations 方法取代。

回應欄位變更

v3 欄位 v4 欄位 附註
status、error_message 已移除 第 4 版使用 HTTP 狀態碼和錯誤主體。
results.address_components.long_name/results.address_components.short_name results.addressComponents.longText/results.addressComponents.shortText 已重新命名。
results.geometry.location_type results.granularity 已重新命名。
results.geometry.location results.location 欄位名稱:lat/lng -> latitude/longitude。
results.geometry.viewport results.viewport 欄位名稱:northeast/southwest -> high/low。
results.postcode_localities results.postalCodeLocalities 已重新命名。現在會傳回一或多個地區 (第 3 版必須 >1)。
results.partial_match 已移除
新功能 results.addressComponents.languageCode 特定地址元件的語言。
新功能 results.bounds 使用 high/low 的明確界限。
新功能 results.place 地點的資源名稱。
新功能 results.postalAddress 結構化 PostalAddress 物件。

重現第 3 版元件篩選器

Geocoding v3 的正向地理編碼包含 components 參數,可對特定元件 (例如 components=country:US) 的結果進行硬篩選。v4 的正向地理編碼不支援在要求參數中進行這類硬篩選。在第 4 版中,您可以將地址資訊提供為路徑中的單一非結構化字串,或結構化查詢參數,例如 address.addressLines、address.locality、address.administrativeArea、address.postalCode 和 address.regionCode。結構化參數不會做為硬性篩選器。而是會將所有提供的元件合併,形成 API 嘗試進行地理編碼的完整地址。API 會在所有元件中,搜尋與指定完整地址最相符的結果。以結構化方式提供元件,有助於 API 瞭解意圖,特別是從個別表單欄位收集地址資訊時。由於每個欄位的資訊類型都很明確,因此 API 可以處理各個元件中的微小錯字或模稜兩可之處。

如要達到類似第 3 版硬性元件篩選器的行為,您必須根據回應中的 postalAddress 和 addressComponents 物件,在第 4 版 API 傳回的 results 陣列上實作用戶端篩選。

下表顯示第 3 版 components 篩選器與第 4 版 postalAddress 欄位的最佳對應關係:

v3 元件篩選器 v4 回應欄位
country postalAddress.regionCode
postal_code postalAddress.postalCode
administrative_area postalAddress.administrativeArea 或 addressComponents

用戶端篩選範例

下列範例說明如何篩選結果,以針對支援的欄位 (國家/地區、行政區和郵遞區號) 達成類似於 v3 元件篩選的行為。不建議篩選其他欄位,因為沒有可靠的篩選條件。

依國家/地區篩選

將要求中的 address.regionCode 與每個結果中的 postalAddress.regionCode 進行比對。請注意,雖然 API 接受要求中的小寫區域代碼,但一律會在回應中傳回大寫代碼,因此您必須先將輸入內容正規化為大寫,才能進行比較。

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')
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');
依行政區篩選

將要求中的 address.administrativeArea 與每個結果中的 postalAddress.administrativeArea 進行比對。與國家/地區代碼類似,您應先將輸入內容正規化為大寫,再進行比較。只有在要求中的 administrativeArea 採用標準 2 字母縮寫時,這項功能才可靠。回應中的 postalAddress.administrativeArea 可能不會直接與 ISO 3166-2 代碼後置字串相符,原因有幾個。首先,在某些地區,ISO 3166-2 代碼對應的子行政區並非郵政地址標準表示法的一部分。舉例來說,在西班牙,addressComponents 可能會顯示第 1 級行政區 (例如「CN」代表加那利群島),但 postalAddress.administrativeArea 可能會包含第 2 級區域 (例如「聖克魯斯德特內里費」)。其次,在某些地區,子分區的縮寫並不常用,因此在 postalAddress.administrativeArea 中會以較長的名稱表示 (基於類似原因,對應子分區的地址元件 addressComponents.shortText 可能與子分區的 ISO 3166-2 代碼後置字元不符)。此外,在某些情況下,子區域可能會以 administrative_area_level_n 的地址元件表示,其中 n 大於 1。 如要取得最完整的結果,您應該檢查 postalAddress.administrativeArea 和任何 addressComponents 中是否有 administrative_area_level_n 類型 (例如 administrative_area_level_1) 的相符項目。

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')
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');
依郵遞區號篩選

將要求中的 address.postalCode 與各項結果中的 postalAddress.postalCode 進行比對。比較前,請務必將輸入和結果郵遞區號正規化。正規化邏輯高度取決於區域。基本做法包括移除空格和連字號,並轉換為一致的大小寫。

如要處理郵遞區號前置字元 (例如英國的「L2」) 或後置字元 (例如美國郵遞區號的「+4」),可能需要更進階的正規化。具體所需的正規化邏輯,會因國家/地區和郵遞區號格式而異。您可能需要調整提供的正規化函式,或為指定區域實作更精密的邏輯。

提供的範例會處理美國郵遞區號,即使提供或傳回 ZIP+4,也能比對 5 位數的郵遞區號。

Python 程式碼範例 (以美國郵遞區號為重點)
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')
Node.js 程式碼範例 (以美國郵遞區號為主)
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');

從 v3 反向地理編碼遷移

如果您使用 v3 反向地理編碼將座標轉換為地址,請遷移至 v4 的「反向地理編碼位置」方法,該方法會接受 GET 要求。

v4 API 變更了名稱、結構和多個參數的支援。強烈建議您使用欄位遮罩,指定要在回應中傳回的欄位。

要求變更參數

v3 參數 v4 參數 附註
language languageCode 已重新命名。如果省略,v3 會使用 Accept-Language 標頭或預設為 en,而 v4 則預設為地點的當地語言和文字。
region regionCode 已重新命名。如果省略,v3 預設為 us,v4 則沒有預設值。
result_type types 已重新命名,並使用重複的查詢參數。
location_type granularity 已重新命名,並使用重複的查詢參數。
extra_computations 已移除 由 SearchDestinations 方法取代。

回應欄位變更

v3 欄位 v4 欄位 附註
status、error_message 已移除 v4 使用 HTTP 狀態碼和錯誤主體。
results.address_components.long_name/results.address_components.short_name results.addressComponents.longText/results.addressComponents.shortText 已重新命名。
results.geometry.location_type results.granularity 已重新命名。
results.geometry.location results.location 欄位名稱:lat/lng -> latitude/longitude。
results.geometry.viewport results.viewport 欄位名稱:northeast/southwest -> high/low。
新功能 results.addressComponents.languageCode 特定地址元件的語言。
新功能 results.bounds 使用 high/low 的明確界限。
新功能 results.place 地點的資源名稱。
新功能 results.postalAddress 結構化 PostalAddress 物件。

從第 3 版地址描述元遷移

如果您使用 address_descriptor 搭配 Geocoding v3 取得地點的其他資訊,則必須改用 SearchDestinationsResponse 的 landmarks 欄位。

從第 3 版地點地理編碼遷移

如果您使用 place_id 透過 Geocoding v3 取得特定地點 ID 的地址,請遷移至 v4 Place Geocoding 方法,該方法會接受 GET 要求。

v4 API 變更了名稱、結構和多個參數的支援。強烈建議您使用欄位遮罩,指定要在回應中傳回的欄位。

要求變更參數

v3 參數 v4 參數 附註
place_id 要求 proto 中的 place 欄位 地點 ID 現在會以路徑參數 places/{place} 的形式提供,例如:https://geocode.googleapis.com/v4/geocode/places/ChIJj61dQgK6j4AR4GeTYWZsKWw。這會對應至基礎要求中的地點欄位。
language languageCode 已重新命名。如果省略,第 3 版會使用 Accept-Language 標頭或預設為 en,而第 4 版則預設為位置的當地語言和指令碼。
region regionCode 已重新命名。如果省略,v3 預設為 us,v4 則沒有預設值。

回應欄位變更

v3 欄位 v4 欄位 附註
status、error_message 已移除 第 4 版使用 HTTP 狀態碼和錯誤主體。
results (root) 第 4 版會傳回單一結果物件,而非 results 陣列。
results.address_components.long_name/results.address_components.short_name addressComponents.longText/addressComponents.shortText 已重新命名。
results.geometry.location_type granularity 已重新命名。
results.geometry.location location 欄位名稱:lat/lng -> latitude/longitude。
results.geometry.viewport viewport 欄位名稱:northeast/southwest -> high/low。
results.postcode_localities postalCodeLocalities 已重新命名。現在會傳回一或多個地區 (第 3 版必須 >1)。
新功能 addressComponents.languageCode 特定地址元件的語言。
新功能 bounds 使用 high/low 的明確界限。
新功能 place 地點的資源名稱。
新功能 postalAddress 結構化 PostalAddress 物件。

從 Geocoding 超地方資料遷移至 Destinations

Geocoding API v3 的下列功能將由 Geocoding API v4 的 SearchDestinations 方法取代:

  • 進入
  • 導覽點
  • 建築物輪廓
  • 園區

如果您先前使用 Geocoding API v3 執行上述功能,請參閱本文件,改用 SearchDestinations 方法取得這些功能。本文說明在 SearchDestinations 回應中,何處可找到這些功能,以及在 Geocoding API 第 3 版和 Geocoding API 第 4 版的 SearchDestinations 方法之間,這些功能在 API 回應中的表示方式有何差異。

進入

如要取得與 destination 相關聯的入口,請使用 destination.entrances 欄位。

請注意,entrance 的格式與 Geocoding API v3 中的入口格式略有不同。destination.entrances 中的每個入口都有下列欄位:

  • displayName:這是新的選填欄位,可為入口提供易於辨識的名稱,例如「B 閘門」。
  • location:這是 LatLng 類型的位置,與 Geocoding API v3 使用的格式不同。
  • tags - 這與 Geocoding API v3 中入口的 tags 欄位相同。
  • place - 類似於 Geocoding API v3 中入口的 buildingPlaceId 欄位。不過,這個欄位中的地點 ID 可以是任何類型的地點,不一定只是建築物。

如要取得與 destination 相關聯的導航點,請使用 destination.navigationPoints 欄位。

請注意,navigationPoint 的格式與 Geocoding API 第 3 版的導航點格式略有不同。destination.navigationPoints 中的每個導覽點都包含下列欄位:

  • displayName:這是新的選填欄位,會顯示導航點的人類可讀名稱,例如「5th Ave」。
  • location:這是 LatLng 類型的地點,與 Geocoding API v3 使用的格式不同。
  • travelModes:與 Geocoding API v3 導航點的 restrictedTravelModes 欄位類似。可能的列舉值相同,唯一的差別在於這個欄位現在代表導航點可接受的交通方式,而非受限的交通方式。
  • usage:這是新欄位,內含導覽點支援的用途。

建築物輪廓

如要取得與 destination 相關聯的建築物輪廓,請使用 destination 中代表建築物的 placeView 物件的 displayPolygon 欄位。您可以透過 placeView.structureType 欄位,檢查每個 placeView 是否為建築物。如果結構類型為 BUILDING,您可以從 placeView.displayPolygon 欄位取得輪廓。placeView 也會提供 Geocoding API 第 3 版沒有的建築物額外欄位。

destination 可包含 placeView 物件,代表下列欄位中的建築物:

  • destination.primary - 這是目的地的主要位置。
  • destination.containingPlaces - 這是重複欄位,可保留「包含」主要地點的較大地點。舉例來說,如果主要地點是 subpremise,containingPlaces 通常會保留代表建築物的 placeView。
  • destination.subDestinations:這是重複欄位,可包含主要地點的子目的地。例如建築物中的個別公寓單位。這個欄位通常不會有代表建築物的 placeView。

請注意,placeView.displayPolygon 的格式與 Geocoding API v3 中的建築物輪廓格式相符,也就是採用 RFC 7946 格式的 GeoJSON 格式。

園區

與建構輪廓類似,如要取得與 destination 相關聯的土地,請使用代表土地的 destinationplaceView 物件中的 displayPolygon 欄位。您可以透過 placeView.structureType 欄位,檢查每個 placeView 是否為理由。如果結構類型為 GROUNDS,您可以從 placeView.displayPolygon 欄位取得大綱。placeView 也會提供 Geocoding API v3 中沒有的額外欄位。

destination 可以有 placeView 物件,代表下列欄位中的理由:

  • destination.primary
  • destination.containingPlaces
  • destination.subDestinations

請注意,placeView.displayPolygon 的格式與 Geocoding API v3 中的場地輪廓格式相符,也就是採用 RFC 7946 格式的 GeoJSON 格式。

結果精確度

在 Geocoding API v3 中,回應幾何圖形中的 location_type 欄位會指出結果的精確度,部分用戶端會根據這些值 (ROOFTOP、RANGE_INTERPOLATED、GEOMETRIC_CENTER 和 APPROXIMATE) 排序或篩選結果。在標準 Geocoding API v4 遷移作業中,這個欄位會重新命名為 granularity。

在 Destinations API (v4 SearchDestinations) 中,沒有 location_type 欄位。而是以不同方式處理空間資訊:

  • 不需手動篩選用戶端:標準地理編碼會提供多個不同精細程度的結果,而 SearchDestinations 方法會盡可能解析為單一最佳目的地,將模糊不清的情況降到最低。這樣一來,用戶端就不需要依地點類型篩選,判斷哪個結果最合適。
  • 以結構類型和顯示多邊形表示的空間資訊: 空間幾何和結構會以以下方式表示:
    • displayPolygon (適用於精確幾何圖形)。
    • placeView 物件中的 structureType 欄位。
  • 結構類型對應:
    • POINT、BUILDING 或 SECTION 的 structureType 通常對應到先前稱為 ROOFTOP 的項目。
    • GROUNDS 的 structureType 通常對應 GEOMETRIC_CENTER。

使用欄位遮罩要求這些功能

SearchDestinations 方法需要欄位遮罩,詳情請參閱「選擇要傳回的欄位」。欄位遮罩可設為 *,以便傳回所有欄位,也可以設為您要接收的特定欄位。舉例來說,下列 API 要求會設定欄位遮罩,以接收取得目的地入口、導覽點、建築物輪廓和地面所需的所有欄位:

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

安全性考量

Geocoding API 第 4 版是設計為伺服器對伺服器 API。JavaScript 使用者無法直接從第 3 版遷移至第 4 版。如果使用 API 金鑰,直接從用戶端 JavaScript (例如在瀏覽器中) 呼叫 v4 方法,API 金鑰很容易遭竊和濫用。

HTTP 參照網址限制雖然實用,但對於網路服務端點來說,保護力仍不足,因為攻擊者可以輕易略過這項限制,在要求中偽造 Referer 標頭。

建議您透過自己的後端伺服器使用 Geocoding API 第 4 版。用戶端應用程式應向這個中介伺服器提出要求,中介伺服器再使用受保護的 API 金鑰 (例如儲存在環境變數或 Secret Manager 中的金鑰),安全地呼叫 Google API。這樣一來,API 金鑰就不會暴露在前端程式碼中。

滿足用戶端需求的替代方案

如果您有需要進行地理編碼的用戶端需求,請考慮使用下列其中一種現有的用戶端解決方案: