A API Geocoding v4 apresenta vários métodos novos que substituem a funcionalidade da v3. Este guia mostra como migrar seu app para usar os novos métodos da v4.
É possível usar as chaves de API atuais com os novos métodos da v4. No entanto, se você solicitou um aumento de cota na v3 da API, será necessário solicitar um aumento nas novas APIs v4.
Migrar da geocodificação direta da v3
Se você usa a Geocoding v3 para geocodificar endereços, migre para o método Geocode an address da v4, que aceita uma solicitação GET.
A API v4 muda nomes, estrutura e suporte para vários parâmetros. Recomendamos que você use uma máscara de campo para especificar os campos que quer que sejam retornados na resposta.
Mudanças nos parâmetros de solicitação
| Parâmetro v3 | Parâmetro v4 | Observações |
|---|---|---|
address, components |
address |
O endereço não estruturado (v3 address) agora é transmitido no caminho do URL. Os componentes de endereço estruturados (v3 components) podem ser transmitidos como parâmetros de consulta address.*. Consulte Reproduzir filtros de componentes da v3. |
bounds |
locationBias.rectangle |
Renomeado. A estrutura mudou para objeto. |
language |
languageCode |
Renomeado. Quando omitido, a v3 usa o cabeçalho Accept-Language ou o padrão en, enquanto a v4 usa o idioma e o script locais do local. |
region |
regionCode |
Renomeado. Quando omitido, a v3 usa us como padrão, enquanto a v4 não tem um valor padrão. |
extra_computations |
Removido | Substituído pelo método SearchDestinations. |
Mudanças no campo de resposta
| Campo v3 | Campo da v4 | Observações |
|---|---|---|
status, error_message |
Removido | A v4 usa códigos de status HTTP e corpos de erro. |
results.address_components.long_name / results.address_components.short_name |
results.addressComponents.longText / results.addressComponents.shortText |
Renomeado. |
results.geometry.location_type |
results.granularity |
Renomeado. |
results.geometry.location |
results.location |
Nomes de campo: lat/lng -> latitude/longitude. |
results.geometry.viewport |
results.viewport |
Nomes de campo: northeast/southwest -> high/low. |
results.postcode_localities |
results.postalCodeLocalities |
Renomeado. Agora é retornado para uma ou mais localidades (a v3 requer >1). |
results.partial_match |
Removido | |
| Nova | results.addressComponents.languageCode |
Idioma do componente de endereço específico. |
| Nova | results.bounds |
Limites explícitos usando high/low. |
| Nova | results.place |
Nome do recurso do lugar. |
| Nova | results.postalAddress |
Objeto PostalAddress estruturado. |
Reproduzir filtros de componentes da v3
A geocodificação direta na versão 3 incluía um parâmetro components que permitia
a filtragem rígida de resultados para componentes específicos (por exemplo,
components=country:US). A geocodificação direta na versão 4 não oferece suporte a esse tipo de
filtragem rígida nos parâmetros de solicitação. Na v4, é possível fornecer informações de endereço como uma única string não estruturada no caminho ou como parâmetros de consulta estruturados, como address.addressLines, address.locality, address.administrativeArea, address.postalCode e address.regionCode.
Os parâmetros estruturados não funcionam como filtros rígidos. Em vez disso, todos os componentes fornecidos são combinados para formar o endereço completo que a API vai tentar geocodificar. A API procura a melhor correspondência para o endereço completo especificado em todos os componentes. Fornecer componentes de maneira estruturada pode ajudar a API a entender melhor a intent, especialmente quando as informações de endereço são coletadas de campos de formulário separados. Isso pode ajudar a API a lidar com pequenos
erros de digitação ou ambiguidades em cada componente, já que o tipo de informação em cada
campo é claro.
Para conseguir um comportamento semelhante aos filtros de componentes rígidos da v3, é necessário implementar
a filtragem do lado do cliente na matriz results retornada pela API v4 com base nos
objetos postalAddress e addressComponents na resposta.
A tabela a seguir mostra a melhor correspondência entre os filtros components da v3 e
os campos postalAddress da v4:
| filtro de componente v3 | Campo de resposta da v4 |
|---|---|
country |
postalAddress.regionCode |
postal_code |
postalAddress.postalCode |
administrative_area |
postalAddress.administrativeArea ou addressComponents |
Exemplos de filtragem do lado do cliente
Os exemplos a seguir mostram como filtrar resultados para alcançar um comportamento semelhante à filtragem de componentes da v3 para campos compatíveis: país, área político-administrativa e código postal. Não é recomendável filtrar outros campos, porque não há critérios de filtragem confiáveis.
Filtrar por país
Combine o address.regionCode da sua solicitação com o postalAddress.regionCode em cada resultado. Embora a API aceite códigos de região em letras minúsculas na solicitação, ela sempre os retorna em letras maiúsculas na resposta. Portanto, é necessário normalizar a entrada para letras maiúsculas antes da comparação.
Exemplo de código 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')
Exemplo de código 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');
Filtrar por área político-administrativa
Combine o address.administrativeArea da sua solicitação com o postalAddress.administrativeArea em cada resultado. Assim como os códigos de país, é preciso normalizar a entrada para letras maiúsculas antes da comparação. Isso só é confiável quando o administrativeArea na sua solicitação é fornecido com uma abreviação padrão de duas letras. O postalAddress.administrativeArea na resposta pode não corresponder diretamente aos sufixos de código ISO 3166-2 por vários motivos. Primeiro, em algumas áreas, a subdivisão correspondente ao código ISO 3166-2 não faz parte da representação padrão de endereços postais. Por exemplo, na Espanha, a área político-administrativa de nível 1 (por exemplo, "CN" para Canárias) pode estar presente em addressComponents, mas postalAddress.administrativeArea pode conter a área de nível 2 (por exemplo, "Santa Cruz de Tenerife"). Em segundo lugar, em algumas áreas, a abreviação da subdivisão não é usada com frequência e é representada em postalAddress.administrativeArea com um nome mais longo. Por motivos semelhantes, o addressComponents.shortText do componente de endereço correspondente à subdivisão pode não corresponder ao sufixo do código ISO 3166-2 da subdivisão. Além disso, em alguns casos, a subdivisão pode ser representada no componente de endereço para administrative_area_level_n com n maior que 1.
Para resultados mais abrangentes, verifique se há uma correspondência em postalAddress.administrativeArea e em qualquer addressComponents com um tipo administrative_area_level_n (por exemplo, administrative_area_level_1).
Exemplo de código 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')
Exemplo de código 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');
Filtrar por código postal
Combine o address.postalCode da sua solicitação com o postalAddress.postalCode em cada resultado. É necessário normalizar os códigos postais de entrada e de resultado antes da comparação. A lógica de normalização depende muito da região. Uma abordagem básica envolve remover espaços e hifens e converter para um padrão consistente.
Uma normalização mais avançada pode ser necessária para lidar com prefixos de código postal (por exemplo, "L2" no Reino Unido) ou sufixos (por exemplo, "+4" nos CEPs dos EUA). A lógica de normalização específica necessária varia de acordo com o país e os formatos dos códigos postais envolvidos. Talvez seja necessário adaptar as funções de normalização fornecidas ou implementar uma lógica mais sofisticada para as regiões que você está segmentando.
O exemplo fornecido lida com CEPs dos EUA e permite a correspondência na base de cinco dígitos, mesmo que o ZIP+4 seja fornecido ou retornado.
Exemplo de código Python (focado em CEPs dos EUA)
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')
Exemplo de código Node.js (focado em CEPs dos EUA)
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');
Migrar da geocodificação reversa da v3
Se você usa a geocodificação inversa da v3 para transformar coordenadas em endereços, migre para o método Geocodificação inversa de um local da v4, que aceita uma solicitação GET.
A API v4 muda nomes, estrutura e suporte para vários parâmetros. Recomendamos que você use uma máscara de campo para especificar os campos que quer que sejam retornados na resposta.
Mudanças nos parâmetros de solicitação
| Parâmetro v3 | Parâmetro v4 | Observações |
|---|---|---|
language |
languageCode |
Renomeado. Quando omitido, a v3 usa o cabeçalho Accept-Language ou o padrão en, enquanto a v4 usa o idioma e o script locais do local. |
region |
regionCode |
Renomeado. Quando omitido, a v3 usa us como padrão, enquanto a v4 não tem um valor padrão. |
result_type |
types |
Renomeado. Usa parâmetros de consulta repetidos. |
location_type |
granularity |
Renomeado. Usa parâmetros de consulta repetidos. |
extra_computations |
Removido | Substituído pelo método SearchDestinations. |
Mudanças no campo de resposta
| Campo v3 | Campo da v4 | Observações |
|---|---|---|
status, error_message |
Removido | A v4 usa códigos de status HTTP e corpos de erro. |
results.address_components.long_name / results.address_components.short_name |
results.addressComponents.longText / results.addressComponents.shortText |
Renomeado. |
results.geometry.location_type |
results.granularity |
Renomeado. |
results.geometry.location |
results.location |
Nomes de campo: lat/lng -> latitude/longitude. |
results.geometry.viewport |
results.viewport |
Nomes de campo: northeast/southwest -> high/low. |
| Nova | results.addressComponents.languageCode |
Idioma do componente de endereço específico. |
| Nova | results.bounds |
Limites explícitos usando high/low. |
| Nova | results.place |
Nome do recurso do lugar. |
| Nova | results.postalAddress |
Objeto PostalAddress estruturado. |
Migrar dos descritores de endereço da v3
Na API Geocoding v3, transmitir extra_computations=ADDRESS_DESCRIPTORS retornava um objeto address_descriptor contendo landmarks[] e areas[]. Na API Geocoding v4, esse recurso é substituído pelo método SearchDestinations (POST /v4/geocode/destinations), que retorna um contexto espacial detalhado diretamente em cada objeto Destination.
A tabela a seguir mapeia os campos legados address_descriptor da v3 para os equivalentes SearchDestinations da v4:
Campo address_descriptor da v3 |
Campo SearchDestinations da v4 |
Notas de migração |
|---|---|---|
landmarks[] |
destinations[].landmarks[] |
Solicite destinations.landmarks no seu X-Goog-FieldMask. |
landmarks[].place_id |
landmarks[].place.placeId |
Encapsulado no objeto place (PlaceView). |
landmarks[].display_name |
landmarks[].place.displayName |
Texto localizado (text e languageCode). |
landmarks[].types |
landmarks[].place.types |
Matriz de strings de tipo de lugar. |
landmarks[].spatial_relationship |
landmarks[].relationalDescription |
Em vez de um tipo enumerado bruto (ACROSS_THE_ROAD, AROUND_THE_CORNER), a v4 retorna uma frase localizada e legível por humanos (por exemplo, "Across from Central Park"). |
landmarks[].straight_line_distance_meters |
landmarks[].straightLineDistanceMeters |
Renomeado para lower camelCase. |
landmarks[].travel_distance_meters |
landmarks[].travelDistanceMeters |
Renomeado para lower camelCase. |
areas[] (tipo enumerado containment) |
destinations[].containingPlaces[] e subDestinations[] |
Equivalente mais próximo disponível para hierarquia estrutural: complexos, campi, shoppings e edifícios são retornados como objetos PlaceView estruturados em containingPlaces[] e subDestinations[] (com structureType definido como GROUNDS ou BUILDING e contornos displayPolygon opcionais). Não há uma substituição direta de 1:1 para áreas de proximidade de bairro/distrito ou o tipo enumerado containment da v3 (NEAR, WITHIN, OUTSKIRTS). |
Migrar da geocodificação de lugares da v3
Se você usa place_id para receber o endereço de um ID de lugar específico com a Geocoding v3, migre para o método Place Geocoding da v4, que aceita uma solicitação GET.
A API v4 muda nomes, estrutura e suporte para vários parâmetros. Recomendamos que você use uma máscara de campo para especificar os campos que quer que sejam retornados na resposta.
Mudanças nos parâmetros de solicitação
| Parâmetro v3 | Parâmetro v4 | Observações |
|---|---|---|
place_id |
Campo place no proto de solicitação |
O ID de lugar agora é fornecido como um parâmetro de caminho places/{place}, por exemplo: https://geocode.googleapis.com/v4/geocode/places/ChIJj61dQgK6j4AR4GeTYWZsKWw. Isso é mapeado para o campo de lugar na solicitação. |
language |
languageCode |
Renomeado. Quando omitido, a v3 usa o cabeçalho Accept-Language ou o padrão en, enquanto a v4 usa o idioma e o script locais do local. |
region |
regionCode |
Renomeado. Quando omitido, a v3 usa us como padrão, enquanto a v4 não tem um valor padrão. |
Mudanças no campo de resposta
| Campo v3 | Campo da v4 | Observações |
|---|---|---|
status, error_message |
Removido | A v4 usa códigos de status HTTP e corpos de erro. |
results |
(raiz) | A v4 retorna um único objeto de resultado, não uma matriz results. |
results.address_components.long_name / results.address_components.short_name |
addressComponents.longText / addressComponents.shortText |
Renomeado. |
results.geometry.location_type |
granularity |
Renomeado. |
results.geometry.location |
location |
Nomes de campo: lat/lng -> latitude/longitude. |
results.geometry.viewport |
viewport |
Nomes de campo: northeast/southwest -> high/low. |
results.postcode_localities |
postalCodeLocalities |
Renomeado. Agora é retornado para uma ou mais localidades (v3 requer >1). |
| Nova | addressComponents.languageCode |
Idioma do componente de endereço específico. |
| Nova | bounds |
Limites explícitos usando high/low. |
| Nova | place |
Nome do recurso do lugar. |
| Nova | postalAddress |
Objeto PostalAddress estruturado. |
Migrar de dados hiperlocais de geocodificação para destinos
Os seguintes recursos da API Geocoding v3 estão sendo substituídos pelo método SearchDestinations da API Geocoding v4:
- Entradas
- Pontos de navegação
- Contornos de edifícios
- Acesso geral
Se você estava usando a API Geocoding v3 para os recursos acima, use este documento
para saber como usar o método SearchDestinations para ter esses recursos.
Neste documento, explicamos onde encontrar esses recursos na resposta de SearchDestinations e as diferenças na representação deles nas respostas da API Geocoding v3 e do método SearchDestinations da API Geocoding v4.
Entradas
Para ver as entradas associadas a um
destination,
use o campo destination.entrances.
Cada entrance
em destination.entrances tem os seguintes campos (substituindo o esquema legado v3 buildings.entrances):
displayName: um novo campo opcional que contém um nome legível por humanos para a entrada, por exemplo,"Gate B".location: um local do tipoLatLngusandolatitudeelongitude(substituindolat/lngda v3).tags: igual ao campotagsdas entradas da API Geocoding v3 (comoPREFERRED).place: nome do recurso do lugar (por exemplo,places/ChIJ...), substituindo o campobuilding_place_idda API Geocoding v3. Na v4, esse lugar pode representar qualquer estrutura de destino (prédio, campus ou parque), não apenas um prédio.
Pontos de navegação
Para ver os pontos de navegação associados a um destination, use o campo
destination.navigationPoints.
Cada navigationPoint
em destination.navigationPoints tem os seguintes campos (substituindo o esquema legado v3 navigation_points):
navigationPointToken: uma string de token criptografada usada para rotear até esse ponto de navegação específico no métodoComputeRoutesda API Routes (Waypoint.navigationPointToken). Consulte Rotear usando tokens de ponto de navegação.displayName: um novo campo opcional que contém um nome legível por humanos para o ponto de navegação, por exemplo,"5th Ave".location: um local do tipoLatLngusandolatitudeelongitude.travelModes: semelhante ao camporestricted_travel_modesda API Geocoding v3, mas a v4 especifica os meios de transporte aceitáveis (DRIVE,WALK) em vez dos restritos.usage: um novo campo que especifica os casos de uso de chegada compatíveis com o ponto de navegação (comoPICKUP,DROPOFFouPARKING).
Contornos de edifícios
Para acessar os contornos de edifícios associados a um destination, use o campo displayPolygon dos objetos placeView no destination que representam edifícios (substituindo a matriz buildings.building_outlines legada da v3). Para cada placeView, verifique se é um edifício com o campo placeView.structureType. Se o tipo de estrutura for BUILDING, você poderá acessar o contorno no campo placeView.displayPolygon. O placeView também terá campos adicionais
para o edifício que não estavam na API Geocoding v3.
Um destination pode ter um objeto placeView que representa um edifício nos seguintes campos:
destination.primary: o lugar principal do destino.destination.containingPlaces: um campo repetido que contém lugares maiores que "contêm" o lugar principal. Por exemplo, se o lugar principal for umsubpremise,containingPlacesgeralmente vai conter oplaceViewque representa o edifício.destination.subDestinations: um campo repetido que contém subdestinos do lugar principal (por exemplo, apartamentos ou suítes individuais em um prédio).
O formato de placeView.displayPolygon corresponde ao formato de contorno de edifício na API Geocoding v3, que é o formato GeoJSON, usando o formato RFC 7946.
Acesso geral
Assim como nos contornos de edifícios, para acessar os terrenos associados a um
destination, use o campo displayPolygon dos objetos placeView
no destination que representam terrenos (substituindo a matriz legada grounds da v3). Para cada placeView, verifique se é um polígono de terreno com o campo placeView.structureType. Se o
tipo de estrutura for GROUNDS, você poderá acessar o contorno no
campo placeView.displayPolygon. A placeView também terá campos adicionais para os motivos que não estavam na API Geocoding v3.
Um destination pode ter um objeto placeView que representa um terreno nos
seguintes campos:
destination.primarydestination.containingPlacesdestination.subDestinations
O formato de placeView.displayPolygon corresponde ao formato de contorno de terrenos na API Geocoding v3, que é o formato GeoJSON, usando o formato RFC 7946.
Precisão dos resultados
Na API Geocoding v3, o campo location_type na geometria de resposta indicava a precisão dos resultados, e alguns clientes classificavam ou filtravam os resultados com base nesses valores (ROOFTOP, RANGE_INTERPOLATED, GEOMETRIC_CENTER e APPROXIMATE). Nas migrações padrão da API Geocoding v4, esse campo é renomeado como granularity.
Na API Destinations (v4 SearchDestinations), não há o campo location_type. Em vez disso, as informações espaciais são processadas de maneira diferente:
- Não é necessário filtrar manualmente no lado do cliente: enquanto a geocodificação padrão
fornece vários resultados em diferentes granularidades, o
método
SearchDestinationsminimiza a ambiguidade ao resolver um único destino otimizado sempre que possível. Isso elimina a necessidade de os clientes filtrarem por tipo de local para determinar qual resultado é o melhor. - Informações espaciais representadas por tipo de estrutura e polígonos de exibição:
a geometria e a estrutura espaciais são indicadas por:
displayPolygon(para geometria exata).- O campo
structureTypeno objetoplaceView.
- Mapeamento de tipo de estrutura:
- Um
structureTypedePOINT,BUILDINGouSECTIONgeralmente corresponde ao que era chamado deROOFTOPanteriormente. - Um
structureTypedeGROUNDSgeralmente corresponde aGEOMETRIC_CENTER.
- Um
Usar uma máscara de campo para solicitar esses recursos
O método SearchDestinations requer uma máscara de campo, conforme explicado em Escolher campos para retornar. A máscara de campo pode ser definida
como * para retornar todos os campos ou como os campos específicos
que você quer receber. Por exemplo, a solicitação de API a seguir define a máscara de campo para receber todos os campos necessários para acessar as entradas, os pontos de navegação, os contornos de edifícios e os terrenos de um destino:
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
Receitas de migração e padrões de código comuns
Ao migrar fluxos de trabalho complexos da Geocoding v3 ou Geocoding++ para SearchDestinations, use as seguintes receitas de código para extrair estruturas comuns de espaço e endereço.
Extrair o melhor polígono de construção
Se você quiser renderizar a planta de um local ou destino:
- Verifique se o lugar
primarytemstructureType === 'BUILDING'e contém umdisplayPolygon. - Caso contrário, inspecione
containingPlacespara encontrar o edifício que o contém (útil quando o destino principal é um subdestino de um edifício maior). - Se nenhum prédio for encontrado, verifique
subDestinationspara ver se os prédios individuais estão listados.
Exemplo de código 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
Exemplo de código 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; }
Extrair contorno do solo
Se você precisar do limite de um condomínio, campus corporativo, shopping center ou parque:
- Se o lugar
primaryrepresenta todo o complexo (structureType === 'GROUNDS'), useprimary.displayPolygon. - Se o lugar
primaryfor um edifício ou uma entrada localizada dentro de um complexo maior, encontre os terrenos ao redor emcontainingPlaces.
Exemplo de código 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
Exemplo de código 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; }
Selecionar pontos de referência para exibição de endereço em comparação com a chegada na última etapa
A Geocoding v3 address_descriptor retornou um tipo enumerado spatial_relationship (WITHIN, BESIDE, BEHIND, NEAR, ACROSS_THE_ROAD, AROUND_THE_CORNER). Em SearchDestinations:
- Não há um tipo enumerado de relacionamento bruto. Em vez disso, use
relationalDescription.textdiretamente. Ele contém frases localizadas e prontas para exibição, como"Across from Central Park"ou"Behind the convention center". Não inclua"Near "manualmente. - Use
tagspara selecionar o ponto de referência certo para seu caso de uso:ARRIVAL: pontos de referência hiperlocais situados imediatamente ao lado, em frente ou do outro lado da rua do destino (normalmente entre 50 e 100 metros). Ideal para chegada de motoristas em tempo real, confirmação de entrega por transportadora ou cartões de chegada no app.ADDRESS: pontos de referência locais no bairro ao redor (normalmente entre 100 e 500 metros). Ideal para finalização de compra, revisão de pedidos ou desambiguação de destino antes da viagem.- Se um ponto de referência tiver as tags
ADDRESSeARRIVAL, ele será conhecido no bairro e estará imediatamente ao lado do destino.
Exemplo de código 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
Exemplo de código 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; }
Traçar rotas para pontos de navegação de veículos e entradas preferenciais
Os fluxos de trabalho de envio e chegada de última etapa combinam dois tipos complementares de pontos de acesso espacial:
- Navegação guiada: direcione os veículos para pontos de desembarque designados usando o
navigationPoints. Os pontos de navegação são pré-classificados por proximidade e relevância. Assim, o primeiro candidato com o modo de viagem desejado (como'DRIVE') e a tag de uso (como'DROPOFF'ou'PICKUP') fornece o waypoint ideal do veículo. Envie onavigationPointTokenpara o métodoComputeRoutes(Waypoint.navigationPointToken) da API Routes ou para o SDK Navigation. Se não houver um ponto de trajeto de carro ajustado à via, use a entrada do edifício ou o centroide principal. - Acesso físico à porta: use
destinations.entrancespara orientar o entregador a pé ou o passageiro até a entrada do prédio. Verifiquetagspara'PREFERRED'para encontrar entradas que provavelmente oferecem acesso físico direto. Se não houver dados de entrada disponíveis, use um ponto de navegação para pedestres (travelModes, incluindo'WALK') ou o centroide principal.
Exemplo de código 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, }
Exemplo de código 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, }; }
Considerações sobre segurança
A API Geocoding v4 foi projetada como uma API de servidor para servidor. Não há um caminho de migração direto para usuários de JavaScript da v3 para a v4. Chamar os métodos da v4 diretamente do JavaScript do lado do cliente (por exemplo, em um navegador) usando uma chave de API expõe essa chave a um alto risco de roubo e uso indevido.
As restrições de referenciador HTTP, embora úteis, não são proteção suficiente para endpoints de serviço da Web, já que podem ser facilmente contornadas por invasores que falsificam o cabeçalho Referer nas solicitações.
Abordagem recomendada
A maneira recomendada de usar a API Geocoding v4 é pelo seu próprio servidor de back-end. Seu aplicativo cliente deve fazer solicitações para esse servidor intermediário, que chama a API do Google de forma segura usando uma chave de API protegida (por exemplo, uma chave armazenada em uma variável de ambiente ou em um gerenciador de secrets). Isso garante que sua chave de API nunca seja exposta no código de front-end.
Alternativas para necessidades do lado do cliente
Se você tiver necessidades do lado do cliente que exijam geocodificação, use uma das soluções disponíveis:
- Serviço Geocoding na API Maps JavaScript: o serviço Geocoding continua usando o back-end v3 e foi projetado para uso em um ambiente de navegador.
- Kit de interface do Places: use o Kit de interface do Places, incluindo elementos do Place Autocomplete, para elementos da interface do usuário relacionados a endereços.