Von Geocoding v3 zu v4 migrieren

Entwickler im Europäischen Wirtschaftsraum (EWR)

In der Geocoding API v4 werden mehrere neue Methoden eingeführt, die Funktionen der API v3 ersetzen. In diesem Leitfaden wird beschrieben, wie Sie Ihre App so migrieren, dass die neuen v4-Methoden verwendet werden.

Sie können Ihre vorhandenen API-Schlüssel mit den neuen v4-Methoden verwenden. Wenn Sie jedoch eine Kontingenterhöhung für Version 3 der API beantragt haben, müssen Sie eine Erhöhung für die neuen Version 4-APIs beantragen.

Von v3 Forward Geocoding migrieren

Wenn Sie v3 Geocoding zum Geocodieren von Adressen verwenden, sollten Sie zur v4-Methode Adresse geocodieren migrieren, die eine GET-Anfrage akzeptiert.

In der v4 API werden Namen, Struktur und Unterstützung für mehrere Parameter geändert. Wir empfehlen dringend, eine Feldmaske zu verwenden, um die Felder anzugeben, die in der Antwort zurückgegeben werden sollen.

Änderungen an Anfrageparametern

v3-Parameter v4-Parameter Hinweise
address, components address Die unstrukturierte Adresse (v3 address) wird jetzt im URL-Pfad übergeben. Strukturierte Adresskomponenten (v3 components) können als address.*-Abfrageparameter übergeben werden. Siehe v3-Komponentenfilter reproduzieren.
bounds locationBias.rectangle Umbenannt; Struktur in Objekt geändert.
language languageCode Umbenannt. Wenn der Parameter weggelassen wird, verwendet v3 den Header Accept-Language oder standardmäßig en, während v4 standardmäßig die lokale Sprache und Schrift des Standorts verwendet.
region regionCode Umbenannt. Wenn keine Angabe gemacht wird, wird in v3 standardmäßig us verwendet, während v4 keinen Standardwert hat.
extra_computations Entfernt Ersetzt durch die Methode SearchDestinations.

Änderungen am Antwortfeld

v3-Feld v4-Feld Hinweise
status, error_message Entfernt v4 verwendet HTTP-Statuscodes und Fehlertextkörper.
results.address_components.long_name/results.address_components.short_name results.addressComponents.longText/results.addressComponents.shortText Umbenannt.
results.geometry.location_type results.granularity Umbenannt.
results.geometry.location results.location Feldnamen: lat/lng -> latitude/longitude.
results.geometry.viewport results.viewport Feldnamen: northeast/southwest -> high/low.
results.postcode_localities results.postalCodeLocalities Umbenannt. Wird jetzt für einen oder mehrere Orte zurückgegeben (v3 erforderlich >1).
results.partial_match Entfernt
Neu results.addressComponents.languageCode Sprache der jeweiligen Adresskomponente.
Neu results.bounds Explizite Grenzen mit high/low.
Neu results.place Ressourcenname für den Ort.
Neu results.postalAddress Strukturiertes PostalAddress-Objekt.

v3-Komponentenfilter reproduzieren

Die Vorwärts-Geocodierung in Geocoding v3 enthielt einen components-Parameter, mit dem Ergebnisse für bestimmte Komponenten (z.B. components=country:US) hart gefiltert werden konnten. Die Vorwärts-Geocodierung in v4 unterstützt diese Art von hartem Filtern in den Anfrageparametern nicht. In v4 können Sie Adressinformationen entweder als einzelnen unstrukturierten String im Pfad oder als strukturierte Suchparameter wie address.addressLines, address.locality, address.administrativeArea, address.postalCode und address.regionCode angeben. Strukturierte Parameter fungieren nicht als feste Filter. Stattdessen werden alle angegebenen Komponenten zu einer vollständigen Adresse kombiniert, die die API dann versucht, per Geocoding zu verarbeiten. Die API sucht nach der besten Übereinstimmung für die gesamte Adresse, die in allen Komponenten angegeben ist. Wenn Sie Komponenten strukturiert bereitstellen, kann die API die Absicht besser verstehen, insbesondere wenn die Adressinformationen aus separaten Formularfeldern stammen. So kann die API kleinere Tippfehler oder Unklarheiten innerhalb der einzelnen Komponenten besser verarbeiten, da der Informationstyp in jedem Feld klar ist.

Wenn Sie ein ähnliches Verhalten wie die harten Komponentenfilter von v3 erzielen möchten, müssen Sie die clientseitige Filterung für das von der v4 API zurückgegebene results-Array basierend auf den postalAddress- und addressComponents-Objekten in der Antwort implementieren.

In der folgenden Tabelle sehen Sie die beste Übereinstimmung zwischen den v3-components-Filtern und den v4-postalAddress-Feldern:

v3-Komponentenfilter v4-Antwortfeld
country postalAddress.regionCode
postal_code postalAddress.postalCode
administrative_area postalAddress.administrativeArea oder addressComponents

Beispiele für clientseitiges Filtern

Die folgenden Beispiele zeigen, wie Sie Ergebnisse filtern, um ein ähnliches Verhalten wie bei der Komponentenfilterung in v3 für unterstützte Felder zu erzielen: Land, Verwaltungsgebiet und Postleitzahl. Es wird nicht empfohlen, nach anderen Feldern zu filtern, da keine zuverlässigen Filterkriterien vorhanden sind.

Nach Land filtern

Gleichen Sie die address.regionCode aus Ihrer Anfrage mit der postalAddress.regionCode in jedem Ergebnis ab. Beachten Sie, dass die API zwar Regionscodes in Kleinbuchstaben in der Anfrage akzeptiert, sie aber in der Antwort immer in Großbuchstaben zurückgibt. Sie müssen Ihre Eingabe also vor dem Vergleich in Großbuchstaben normalisieren.

Python-Codebeispiel
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-Codebeispiel
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');
Nach Verwaltungsgebiet filtern

Gleichen Sie die address.administrativeArea aus Ihrer Anfrage mit der postalAddress.administrativeArea in jedem Ergebnis ab. Ähnlich wie bei Ländercodes sollten Sie Ihre Eingabe vor dem Vergleich in Großbuchstaben normalisieren. Dies ist nur zuverlässig, wenn die administrativeArea in Ihrer Anfrage mit einer standardmäßigen zweistelligen Abkürzung angegeben ist. Der postalAddress.administrativeArea in der Antwort stimmt aus mehreren Gründen möglicherweise nicht direkt mit den Suffixen des ISO 3166-2-Codes überein. Erstens ist in einigen Regionen die Unterteilung, die dem ISO 3166-2-Code entspricht, nicht Teil der Standarddarstellung von Postadressen. In Spanien kann beispielsweise die Verwaltungsebene 1 (z.B. „CN“ für Canarias) in addressComponents enthalten sein, während postalAddress.administrativeArea die Verwaltungsebene 2 (z.B. „Santa Cruz de Tenerife“) enthalten kann. Zweitens wird in einigen Regionen die Abkürzung der Untereinheit nicht häufig verwendet und in postalAddress.administrativeArea mit einem längeren Namen dargestellt. Aus ähnlichen Gründen stimmt addressComponents.shortText für die Adresskomponente, die der Untereinheit entspricht, möglicherweise nicht mit dem ISO 3166-2-Codesuffix der Untereinheit überein. Außerdem kann die Untereinheit in einigen Fällen in der Adresskomponente für administrative_area_level_n mit n > 1 dargestellt werden. Die umfassendsten Ergebnisse erhalten Sie, wenn Sie sowohl in postalAddress.administrativeArea als auch in allen addressComponents mit dem Typ administrative_area_level_n (z.B. administrative_area_level_1) nach einer Übereinstimmung suchen.

Python-Codebeispiel
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-Codebeispiel
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');
Nach Postleitzahl filtern

Gleichen Sie die address.postalCode aus Ihrer Anfrage mit der postalAddress.postalCode in jedem Ergebnis ab. Sie müssen sowohl die Eingabe- als auch die Ergebnispostleitzahlen vor dem Vergleich normalisieren. Die Normalisierungslogik ist stark von der Region abhängig. Ein grundlegender Ansatz besteht darin, Leerzeichen und Bindestriche zu entfernen und die Groß-/Kleinschreibung einheitlich zu gestalten.

Für Postleitzahlenpräfixe (z.B. „L2“ im Vereinigten Königreich) oder ‑suffixe (z.B. „+4“ in US-Postleitzahlen) ist möglicherweise eine erweiterte Normalisierung erforderlich. Die erforderliche Normalisierungslogik variiert je nach Land und Format der Postleitzahlen. Möglicherweise müssen Sie die bereitgestellten Normalisierungsfunktionen anpassen oder eine komplexere Logik für die Zielregionen implementieren.

Das bereitgestellte Beispiel verarbeitet US-Postleitzahlen und ermöglicht den Abgleich auf der Grundlage der fünfstelligen Basis, auch wenn ZIP+4 angegeben oder zurückgegeben wird.

Python-Codebeispiel (US-Postleitzahlen)
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-Codebeispiel (US-Postleitzahlen)
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');

Von der umgekehrten Geocodierung in v3 migrieren

Wenn Sie die umgekehrte Geocodierung von Version 3 verwenden, um Koordinaten in Adressen umzuwandeln, sollten Sie zur Methode Umgekehrte Geocodierung für einen Standort von Version 4 migrieren, die eine GET-Anfrage akzeptiert.

In der v4 API werden Namen, Struktur und Unterstützung für mehrere Parameter geändert. Wir empfehlen dringend, eine Feldmaske zu verwenden, um die Felder anzugeben, die in der Antwort zurückgegeben werden sollen.

Änderungen an Anfrageparametern

v3-Parameter v4-Parameter Hinweise
language languageCode Umbenannt. Wenn der Parameter weggelassen wird, verwendet v3 den Header Accept-Language oder standardmäßig en, während v4 standardmäßig die lokale Sprache und Schrift des Standorts verwendet.
region regionCode Umbenannt. Wenn keine Angabe gemacht wird, wird in v3 standardmäßig us verwendet, während v4 keinen Standardwert hat.
result_type types Umbenannt; verwendet wiederholte Abfrageparameter.
location_type granularity Umbenannt; verwendet wiederholte Abfrageparameter.
extra_computations Entfernt Ersetzt durch die Methode SearchDestinations.

Änderungen am Antwortfeld

v3-Feld v4-Feld Hinweise
status, error_message Entfernt v4 verwendet HTTP-Statuscodes und Fehlertextkörper.
results.address_components.long_name/results.address_components.short_name results.addressComponents.longText/results.addressComponents.shortText Umbenannt.
results.geometry.location_type results.granularity Umbenannt.
results.geometry.location results.location Feldnamen: lat/lng -> latitude/longitude.
results.geometry.viewport results.viewport Feldnamen: northeast/southwest -> high/low.
Neu results.addressComponents.languageCode Sprache der jeweiligen Adresskomponente.
Neu results.bounds Explizite Grenzen mit high/low.
Neu results.place Ressourcenname für den Ort.
Neu results.postalAddress Strukturiertes PostalAddress-Objekt.

Von v3-Adressdeskriptoren migrieren

In der Geocoding API v3 wurde bei der Übergabe von extra_computations=ADDRESS_DESCRIPTORS ein address_descriptor-Objekt mit landmarks[] und areas[] zurückgegeben. In der Geocoding API v4 wird diese Funktion durch die Methode SearchDestinations (POST /v4/geocode/destinations) ersetzt, die umfangreichen räumlichen Kontext direkt in jedem Destination-Objekt zurückgibt.

In der folgenden Tabelle sind die alten v3-address_descriptor-Felder den entsprechenden v4-SearchDestinations-Feldern zugeordnet:

v3-Feld address_descriptor v4-SearchDestinations-Feld Migrationshinweise
landmarks[] destinations[].landmarks[] Fordern Sie destinations.landmarks in Ihrem X-Goog-FieldMask an.
landmarks[].place_id landmarks[].place.placeId Im place-Objekt (PlaceView) verpackt.
landmarks[].display_name landmarks[].place.displayName Lokalisierter Text (text und languageCode).
landmarks[].types landmarks[].place.types Array von Ortstyp-Strings.
landmarks[].spatial_relationship landmarks[].relationalDescription Anstelle eines Roh-Enums (ACROSS_THE_ROAD, AROUND_THE_CORNER) gibt v4 eine lokalisierte, menschenlesbare Wortgruppe zurück (z.B. "Across from Central Park").
landmarks[].straight_line_distance_meters landmarks[].straightLineDistanceMeters In lowerCamelCase umbenannt.
landmarks[].travel_distance_meters landmarks[].travelDistanceMeters In lowerCamelCase umbenannt.
areas[] (containment-Enum) destinations[].containingPlaces[] und subDestinations[] Nächstgelegene verfügbare Entsprechung für die strukturelle Hierarchie: Übergeordnete Komplexe, Campus, Einkaufszentren und Gebäude werden als strukturierte PlaceView-Objekte in containingPlaces[] und subDestinations[] zurückgegeben (wobei structureType auf GROUNDS oder BUILDING festgelegt ist und optionale displayPolygon-Umrisse vorhanden sind). Beachten Sie, dass es keinen direkten 1:1-Ersatz für Nachbarschafts-/Bezirksnähebereiche oder das v3-containment-Enum (NEAR, WITHIN, OUTSKIRTS) gibt.

Von v3-Place-Geocoding migrieren

Wenn Sie place_id verwenden, um die Adresse für eine bestimmte Orts-ID mit Geocoding v3 abzurufen, müssen Sie zur Methode Place Geocoding der Version 4 migrieren, die eine GET-Anfrage akzeptiert.

In der v4 API werden Namen, Struktur und Unterstützung für mehrere Parameter geändert. Wir empfehlen dringend, eine Feldmaske zu verwenden, um die Felder anzugeben, die in der Antwort zurückgegeben werden sollen.

Änderungen an Anfrageparametern

v3-Parameter v4-Parameter Hinweise
place_id Feld place im Anfrage-Proto Die Orts-ID wird jetzt als Pfadparameter places/{place} angegeben, z. B. https://geocode.googleapis.com/v4/geocode/places/ChIJj61dQgK6j4AR4GeTYWZsKWw. Dies entspricht dem Ortsfeld in der zugrunde liegenden Anfrage.
language languageCode Umbenannt. Wenn der Parameter weggelassen wird, verwendet v3 den Header Accept-Language oder standardmäßig en, während v4 standardmäßig die lokale Sprache und Schrift des Standorts verwendet.
region regionCode Umbenannt. Wenn keine Angabe gemacht wird, wird in v3 standardmäßig us verwendet, während v4 keinen Standardwert hat.

Änderungen am Antwortfeld

v3-Feld v4-Feld Hinweise
status, error_message Entfernt v4 verwendet HTTP-Statuscodes und Fehlertextkörper.
results (root) v4 gibt ein einzelnes Ergebnisobjekt zurück, kein results-Array.
results.address_components.long_name/results.address_components.short_name addressComponents.longText/addressComponents.shortText Umbenannt.
results.geometry.location_type granularity Umbenannt.
results.geometry.location location Feldnamen: lat/lng -> latitude/longitude.
results.geometry.viewport viewport Feldnamen: northeast/southwest -> high/low.
results.postcode_localities postalCodeLocalities Umbenannt. Wird jetzt für einen oder mehrere Orte zurückgegeben (v3 erforderlich >1).
Neu addressComponents.languageCode Sprache der jeweiligen Adresskomponente.
Neu bounds Explizite Grenzen mit high/low.
Neu place Ressourcenname für den Ort.
Neu postalAddress Strukturiertes PostalAddress-Objekt.

Von hyperlokalen Geocoding-Daten zu Zielen migrieren

Die folgenden Funktionen der Geocoding API v3 werden durch die Methode SearchDestinations der Geocoding API v4 ersetzt:

  • Einstiege
  • Navigationspunkte
  • Gebäudeumrisse
  • Außengelände

Wenn Sie die Geocoding API v3 für die oben genannten Funktionen verwendet haben, können Sie stattdessen die SearchDestinations-Methode verwenden, um diese Funktionen zu nutzen. In diesem Dokument wird erläutert, wo Sie diese Funktionen in der SearchDestinations-Antwort finden und wie sich die Darstellung dieser Funktionen in den API-Antworten zwischen der Geocoding API v3 und der SearchDestinations-Methode der Geocoding API v4 unterscheidet.

Einstiege

Verwenden Sie das Feld destination.entrances, um die Eingänge abzurufen, die mit einem destination verknüpft sind.

Jedes entrance in destination.entrances enthält die folgenden Felder (ersetzt das alte v3-buildings.entrances-Schema):

  • displayName: Ein neues optionales Feld, das einen menschenlesbaren Namen für den Eingang enthält, z. B. "Gate B".
  • location: ein Standort vom Typ LatLng mit latitude und longitude (ersetzt v3 lat/lng).
  • tags: entspricht dem Feld tags aus den Eingängen der Geocoding API v3 (z. B. PREFERRED).
  • place: Ressourcenname des Orts (z. B. places/ChIJ...), der das Feld building_place_id aus der Geocoding API v3 ersetzt. In v4 kann dieser Ort jede Zielstruktur (Gebäude, Campus oder Park) darstellen, nicht nur ein Gebäude.

Verwenden Sie das Feld destination.navigationPoints, um die Navigationspunkte abzurufen, die mit einem destination verknüpft sind.

Jedes navigationPoint in destination.navigationPoints enthält die folgenden Felder (ersetzt das alte v3-navigation_points-Schema):

  • navigationPointToken: Ein verschlüsselter Tokenstring, der verwendet wird, um in der Routes API-Methode ComputeRoutes (Waypoint.navigationPointToken) zu diesem bestimmten Navigationspunkt zu routen. Weitere Informationen finden Sie unter Route mit Navigationspunkt-Tokens berechnen.
  • displayName: Ein neues optionales Feld, das einen menschenlesbaren Namen für den Navigationspunkt enthält, z. B. "5th Ave".
  • location: ein Standort vom Typ LatLng mit latitude und longitude.
  • travelModes: Ähnlich wie das Feld restricted_travel_modes aus der Geocoding API v3, nur dass in Version 4 zulässige Mobilitätsformen (DRIVE, WALK) anstelle von eingeschränkten Mobilitätsformen angegeben werden.
  • usage: Ein neues Feld, in dem die unterstützten Anwendungsfälle für die Ankunft am Navigationspunkt angegeben werden (z. B. PICKUP, DROPOFF oder PARKING).

Gebäudeumrisse

Wenn Sie die mit einem destination verknüpften Gebäudeumrisse abrufen möchten, verwenden Sie das Feld displayPolygon der placeView-Objekte im destination, die Gebäude darstellen. Dadurch wird das alte v3-buildings.building_outlines-Array ersetzt. Prüfen Sie für jedes placeView mit dem Feld placeView.structureType, ob es sich um ein Gebäude handelt. Wenn der Strukturtyp BUILDING ist, können Sie den Umriss aus dem Feld placeView.displayPolygon abrufen. Die placeView enthält außerdem zusätzliche Felder für das Gebäude, die in der Geocoding API v3 nicht vorhanden waren.

Ein destination kann ein placeView-Objekt enthalten, das ein Gebäude in den folgenden Feldern darstellt:

  • destination.primary: der primäre Ort für das Ziel.
  • destination.containingPlaces: Ein wiederkehrendes Feld, das größere Orte enthält, die den primären Ort „enthalten“. Wenn der primäre Ort beispielsweise ein subpremise ist, enthält containingPlaces normalerweise die placeView, die das Gebäude darstellt.
  • destination.subDestinations: Ein wiederkehrendes Feld, das Unterziele des Hauptorts enthält (z. B. einzelne Apartments oder Suiten in einem Gebäude).

Das Format von placeView.displayPolygon entspricht dem Gebäudeumrissformat in der Geocoding API v3, also dem GeoJSON-Format, das das RFC 7946-Format verwendet.

Außengelände

Ähnlich wie bei Gebäudeumrissen können Sie die mit einem destination verknüpften Grundstücke über das Feld displayPolygon der placeView-Objekte im destination abrufen, die Grundstücke darstellen. Dadurch wird das alte v3-grounds-Array ersetzt. Prüfen Sie für jedes placeView, ob es sich um ein Polygon für ein Gelände handelt. Verwenden Sie dazu das Feld placeView.structureType. Wenn der Strukturtyp GROUNDS ist, können Sie den Umriss aus dem Feld placeView.displayPolygon abrufen. Die placeView enthält außerdem zusätzliche Felder für die Gründe, die in der Geocoding API v3 nicht enthalten waren.

Ein destination kann ein placeView-Objekt haben, das ein Gelände in den folgenden Feldern darstellt:

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

Das Format von placeView.displayPolygon entspricht dem Format für die Umrisse von Geländen in der Geocoding API v3, also dem GeoJSON-Format, wobei das RFC 7946-Format verwendet wird.

Genauigkeit der Ergebnisse

In der Geocoding API v3 gab das Feld location_type in der Antwortgeometrie die Genauigkeit der Ergebnisse an. Einige Clients haben die Ergebnisse anhand dieser Werte (ROOFTOP, RANGE_INTERPOLATED, GEOMETRIC_CENTER und APPROXIMATE) sortiert oder gefiltert. Bei Standardmigrationen zur Geocoding API v4 wird dieses Feld in granularity umbenannt.

In der Destinations API (v4 SearchDestinations) gibt es kein location_type-Feld. Stattdessen werden räumliche Informationen anders verarbeitet:

  • Keine manuelle clientseitige Filterung erforderlich: Während die Standard-Geocoding API mehrere Ergebnisse mit unterschiedlichen Detaillierungsgraden liefert, minimiert die Methode SearchDestinations Mehrdeutigkeiten, indem sie nach Möglichkeit ein einzelnes, optimiertes Ziel auflöst. So müssen Kunden nicht mehr nach Standorttyp filtern, um das beste Ergebnis zu finden.
  • Räumliche Informationen, die durch Strukturtyp und Anzeigepolygone dargestellt werden: Räumliche Geometrie und Struktur werden durch Folgendes angegeben:
    • displayPolygon (für die genaue Geometrie)
    • Das Feld structureType im Objekt placeView.
  • Zuordnung des Gebäudetyps:
    • Ein structureType von POINT, BUILDING oder SECTION entspricht im Allgemeinen dem, was zuvor als ROOFTOP bezeichnet wurde.
    • Ein structureType von GROUNDS entspricht im Allgemeinen GEOMETRIC_CENTER.

Feldmaske verwenden, um diese Funktionen anzufordern

Für die Methode SearchDestinations ist eine Feldmaske erforderlich, wie unter Felder für die Rückgabe auswählen beschrieben. Die Feldmaske kann auf * gesetzt werden, um alle Felder zurückzugeben, oder Sie können sie auf die spezifischen Felder festlegen, die Sie erhalten möchten. In der folgenden API-Anfrage wird beispielsweise die Feldmaske so festgelegt, dass alle Felder zurückgegeben werden, die für die Eingänge, Navigationspunkte, Gebäudeumrisse und das Gelände eines Ziels erforderlich sind:

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

Häufige Migrationsrezepte und Codemuster

Wenn Sie komplexe Workflows von Geocoding v3 oder Geocoding++ zu SearchDestinations migrieren, können Sie die folgenden Codebeispiele verwenden, um gängige räumliche und Adressstrukturen zu extrahieren.

Bestes Gebäudepolygon extrahieren

So rendern Sie den Gebäudegrundriss für einen Ort oder ein Ziel:

  1. Prüfen Sie, ob der Ort primary den Wert structureType === 'BUILDING' hat und einen displayPolygon enthält.
  2. Wenn nicht, prüfen Sie containingPlaces, um das umschließende Gebäude zu finden. Das ist nützlich, wenn das Hauptziel ein Unterziel eines größeren Gebäudes ist.
  3. Wenn kein umschließendes Gebäude gefunden wird, prüfen Sie subDestinations, ob einzelne Gebäude aufgeführt sind.
Python-Codebeispiel
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
Node.js-Codebeispiel
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;
}

Umriss des Geländes extrahieren

Wenn Sie die Grenzen eines Wohnkomplexes, eines Firmengeländes, eines Einkaufszentrums oder eines Parks benötigen:

  1. Wenn der Ort primary den gesamten Komplex (structureType === 'GROUNDS') darstellt, verwenden Sie primary.displayPolygon.
  2. Wenn der Ort primary ein Gebäude oder ein Eingang innerhalb eines größeren Komplexes ist, suchen Sie in containingPlaces nach dem umschließenden Gelände.
Python-Codebeispiel
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
Node.js-Codebeispiel
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;
}

Sehenswürdigkeiten für die Adressanzeige im Vergleich zur Ankunft auf der letzten Meile auswählen

Geocoding v3 address_descriptor hat ein spatial_relationship-Enum (WITHIN, BESIDE, BEHIND, NEAR, ACROSS_THE_ROAD, AROUND_THE_CORNER) zurückgegeben. In SearchDestinations:

  • Es gibt kein Enum für die Rohbeziehung. Verwenden Sie stattdessen relationalDescription.text direkt. Sie enthält lokalisierte, anzeigefertige Wortgruppen wie "Across from Central Park" oder "Behind the convention center". Stellen Sie "Near " nicht manuell voran.
  • Wählen Sie mit tags die richtige Landmarke für Ihren Anwendungsfall aus:
    • ARRIVAL: Hyperlokale Sehenswürdigkeiten, die sich direkt neben, gegenüber oder auf der anderen Straßenseite des Ziels befinden (normalerweise innerhalb von 50–100 Metern). Am besten geeignet für die Ankunft von Fahrern in Echtzeit, die Bestätigung der Lieferung durch Kuriere oder Ankunftskarten in der App.
    • ADDRESS: Lokale Sehenswürdigkeiten in der Umgebung (normalerweise im Umkreis von 100–500 Metern). Am besten geeignet für die Kasse, die Bestellübersicht oder die Mehrdeutigkeitsauflösung von Zielen vor der Fahrt.
    • Wenn eine Sehenswürdigkeit sowohl das Tag ADDRESS als auch das Tag ARRIVAL hat, ist sie in der Umgebung bekannt und befindet sich direkt neben dem Ziel.
Python-Codebeispiel
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
Node.js-Codebeispiel
/**
 * 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;
}

Routen zu Navigationspunkten für Fahrzeuge und bevorzugten Eingängen

Bei Workflows für die Zustellung und Ankunft auf der letzten Meile werden zwei sich ergänzende Arten von räumlichen Zugangspunkten kombiniert:

  • Detaillierte Routenführung: Fahrzeuge mit navigationPoints zu bestimmten Absetzpunkten auf der Straße leiten. Navigationspunkte werden vorab nach Nähe und Relevanz sortiert. Der erste Kandidat mit dem gewünschten Reisemodus (z. B. 'DRIVE') und dem gewünschten Nutzungs-Tag (z. B. 'DROPOFF' oder 'PICKUP') ist der optimale Wegpunkt für das Fahrzeug. Senden Sie die navigationPointToken an die Routes API-Methode ComputeRoutes (Waypoint.navigationPointToken) oder das Navigation SDK. Wenn kein an die Straße angepasster Fahrpunkt vorhanden ist, wird auf den Gebäudeeingang oder den primären Schwerpunkt zurückgegriffen.
  • Physischer Zugang: Führen Sie den Kurier zu Fuß oder den Fahrgast mithilfe von destinations.entrances zum Gebäudeeingang. Suchen Sie in tags nach 'PREFERRED', um Eingänge zu finden, die wahrscheinlich direkten physischen Zugang bieten. Wenn keine Daten zu Eingängen verfügbar sind, wird auf einen Navigationspunkt für Fußgänger (travelModes einschließlich 'WALK') oder den primären Schwerpunkt zurückgegriffen.
Python-Codebeispiel
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,
    }
Node.js-Codebeispiel
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,
    };
}

Sicherheitsaspekte

Die Geocoding API v4 ist als Server-zu-Server-API konzipiert. Es gibt keinen direkten Migrationspfad für JavaScript-Nutzer von Version 3 zu Version 4. Wenn Sie die v4-Methoden direkt über clientseitiges JavaScript (z. B. in einem Browser) mit einem API-Schlüssel aufrufen, besteht ein hohes Risiko, dass Ihr API-Schlüssel gestohlen und missbraucht wird.

HTTP-Referrer-Einschränkungen sind zwar nützlich, bieten aber keinen ausreichenden Schutz für Webdienst-Endpunkte, da sie von Angreifern, die den Referer-Header in ihren Anfragen fälschen, leicht umgangen werden können.

Die empfohlene Methode zur Verwendung der Geocoding API v4 ist über Ihren eigenen Backend-Server. Ihre Clientanwendung sollte Anfragen an diesen Zwischenserver senden, der dann die Google API sicher mit einem geschützten API-Schlüssel aufruft (z. B. einem Schlüssel, der in einer Umgebungsvariablen oder einem Secret Manager gespeichert ist). So wird sichergestellt, dass Ihr API-Schlüssel nie im Frontend-Code offengelegt wird.

Alternativen für clientseitige Anforderungen

Wenn Sie clientseitige Anforderungen haben, die Geocoding erfordern, sollten Sie eine der vorhandenen clientseitigen Lösungen verwenden:

  • Geocoding-Dienst in der Maps JavaScript API: Der Geocoding-Dienst verwendet weiterhin das v3-Backend und ist für die Verwendung in einer Browserumgebung konzipiert.
  • Places UI Kit: Verwenden Sie das Places UI Kit, einschließlich der Place Autocomplete-Elemente, für adressbezogene Elemente der Benutzeroberfläche.