La versión 4 de la API de Geocoding presenta varios métodos nuevos que reemplazan la funcionalidad de la versión 3 de la API. En esta guía, se muestra cómo migrar tu app para usar los nuevos métodos de la versión 4.
Puedes usar tus claves de API existentes con los nuevos métodos de la versión 4. Sin embargo, si solicitaste un aumento de cuota en la versión 3 de la API, debes solicitar un aumento en las nuevas APIs de la versión 4.
Migra desde la geocodificación directa de la versión 3
Si usas Geocoding v3 para geocodificar direcciones, debes migrar al método v4 Geocode an address, que acepta una solicitud GET.
La API v4 cambia los nombres, la estructura y la compatibilidad de varios parámetros. Te recomendamos que uses una máscara de campo para especificar los campos que deseas que se muestren en la respuesta.
Cambios en los parámetros de solicitud
| Parámetro de v3 | Parámetro de v4 | Notas |
|---|---|---|
address, components |
address |
La dirección no estructurada (v3 address) ahora se pasa en la ruta de URL. Los componentes de dirección estructurados (components de la versión 3) se pueden pasar como parámetros de consulta address.*. Consulta Reproduce los filtros de componentes de la versión 3. |
bounds |
locationBias.rectangle |
Se cambió el nombre y la estructura cambió a objeto. |
language |
languageCode |
Se cambió el nombre. Cuando se omite, la versión 3 usa el encabezado Accept-Language o, de forma predeterminada, en, mientras que la versión 4 usa de forma predeterminada el idioma y la escritura locales de la ubicación. |
region |
regionCode |
Se cambió el nombre. Cuando se omite, la versión 3 se establece de forma predeterminada en us, mientras que la versión 4 no tiene un valor predeterminado. |
extra_computations |
Eliminado | Se reemplazó por el método SearchDestinations. |
Cambios en el campo de respuesta
| Campo de v3 | Campo v4 | Notas |
|---|---|---|
status, error_message |
Eliminado | La versión 4 usa códigos de estado HTTP y cuerpos de error. |
results.address_components.long_name/results.address_components.short_name |
results.addressComponents.longText/results.addressComponents.shortText |
Se cambió el nombre. |
results.geometry.location_type |
results.granularity |
Se cambió el nombre. |
results.geometry.location |
results.location |
Nombres de los campos: lat/lng -> latitude/longitude. |
results.geometry.viewport |
results.viewport |
Nombres de los campos: northeast/southwest -> high/low. |
results.postcode_localities |
results.postalCodeLocalities |
Se cambió el nombre. Ahora se devuelve para una o más localidades (la versión 3 requería más de 1). |
results.partial_match |
Eliminado | |
| Nuevo | results.addressComponents.languageCode |
Es el idioma del componente de dirección específico. |
| Nuevo | results.bounds |
Límites explícitos con high/low. |
| Nuevo | results.place |
Es el nombre del recurso del lugar. |
| Nuevo | results.postalAddress |
Objeto PostalAddress estructurado. |
Reproduce los filtros de componentes de la versión 3
La geocodificación directa en Geocoding v3 incluía un parámetro components que habilitaba
el filtrado estricto de resultados para componentes específicos (p.ej.,
components=country:US). La geocodificación directa en v4 no admite este tipo de
filtrado estricto en los parámetros de la solicitud. En la versión 4, puedes proporcionar información de la dirección como una sola cadena no estructurada en la ruta de acceso o como parámetros de consulta estructurados, como address.addressLines, address.locality, address.administrativeArea, address.postalCode y address.regionCode.
Los parámetros estructurados no actúan como filtros estrictos. En cambio, todos los componentes proporcionados se combinan para formar la dirección completa que la API intentará geocodificar. La API busca la mejor coincidencia para la dirección completa especificada en todos los componentes. Proporcionar componentes de forma estructurada puede ayudar a la API a comprender mejor la intención, en especial cuando la información de la dirección se recopila de campos de formulario separados. Esto puede ayudar a la API a controlar errores tipográficos o ambigüedades menores dentro de cada componente, ya que el tipo de información en cada campo es claro.
Para lograr un comportamiento similar al de los filtros de componentes estrictos de la versión 3, debes implementar
el filtrado del cliente en el array results que muestra la API de la versión 4 según los
objetos postalAddress y addressComponents de la respuesta.
En la siguiente tabla, se muestra la mejor coincidencia entre los filtros components de la versión 3 y
los campos postalAddress de la versión 4:
| Filtro de componentes de la versión 3 | Campo de respuesta de v4 |
|---|---|
country |
postalAddress.regionCode |
postal_code |
postalAddress.postalCode |
administrative_area |
postalAddress.administrativeArea o addressComponents |
Ejemplos de filtrado del cliente
En los siguientes ejemplos, se muestra cómo filtrar los resultados para lograr un comportamiento similar al filtrado de componentes de la versión 3 para los campos admitidos: país, área administrativa y código postal. No se recomienda filtrar por otros campos, ya que no existen criterios de filtrado confiables.
Filtrar por país
Haz coincidir el address.regionCode de tu solicitud con el postalAddress.regionCode de cada resultado. Ten en cuenta que, si bien la API acepta códigos de región en minúsculas en la solicitud, siempre los devuelve en mayúsculas en la respuesta, por lo que debes normalizar la entrada a mayúsculas antes de la comparación.
Ejemplo de código de 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')
Ejemplo de código de 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 administrativa
Haz coincidir el address.administrativeArea de tu solicitud con el postalAddress.administrativeArea de cada resultado. Al igual que con los códigos de país, debes normalizar la entrada a mayúsculas antes de la comparación. Esto solo es confiable cuando el administrativeArea de tu solicitud se proporciona con una abreviatura estándar de 2 letras. Es posible que el postalAddress.administrativeArea de la respuesta no coincida directamente con los sufijos de código ISO 3166-2 por varios motivos. En primer lugar, en algunas áreas, la subdivisión correspondiente al código ISO 3166-2 no forma parte de la representación estándar de las direcciones postales. Por ejemplo, en España, el nivel 1 del área administrativa (p.ej., "CN" para Canarias) podría estar presente en addressComponents, pero postalAddress.administrativeArea podría contener el área de nivel 2 (p.ej., "Santa Cruz de Tenerife"). En segundo lugar, en algunas áreas, la abreviatura de la subdivisión
no se usa con frecuencia y se representa en postalAddress.administrativeArea
con un nombre más largo (por motivos similares, es posible que addressComponents.shortText para el componente de dirección
correspondiente a la subdivisión no coincida con el sufijo del código ISO 3166-2 de la subdivisión). Además, en algunos casos, la subdivisión se puede representar en el componente de dirección para administrative_area_level_n con n mayor que 1.
Para obtener los resultados más completos, debes verificar si hay coincidencias tanto en postalAddress.administrativeArea como en cualquier addressComponents con un tipo administrative_area_level_n (p.ej., administrative_area_level_1).
Ejemplo de código de 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')
Ejemplo de código de 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
Haz coincidir el address.postalCode de tu solicitud con el postalAddress.postalCode de cada resultado. Debes normalizar los códigos postales de entrada y de resultado antes de la comparación. La lógica de normalización depende en gran medida de la región. Un enfoque básico implica quitar los espacios y los guiones, y convertir el texto a un uso de mayúsculas y minúsculas coherente.
Es posible que se necesite una normalización más avanzada para controlar los prefijos de los códigos postales (p. ej., "L2" en el Reino Unido) o los sufijos (p. ej., "+4" en los códigos postales de EE.UU.). La lógica de normalización específica requerida variará según el país y los formatos de los códigos postales involucrados. Es posible que debas adaptar las funciones de normalización proporcionadas o implementar una lógica más sofisticada para las regiones a las que te orientas.
El ejemplo proporcionado controla los códigos postales de EE.UU. y permite la coincidencia en la base de 5 dígitos, incluso si se proporciona o se devuelve el código ZIP+4.
Ejemplo de código de Python (enfocado en códigos postales de EE.UU.)
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')
Ejemplo de código de Node.js (enfocado en el código postal de EE.UU.)
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');
Migra desde la geocodificación inversa de la versión 3
Si usas la geocodificación inversa de la versión 3 para convertir coordenadas en direcciones, debes migrar al método Geocodificación inversa de una ubicación de la versión 4, que acepta una solicitud GET.
La API v4 cambia los nombres, la estructura y la compatibilidad de varios parámetros. Te recomendamos que uses una máscara de campo para especificar los campos que deseas que se muestren en la respuesta.
Cambios en los parámetros de solicitud
| Parámetro de v3 | Parámetro de v4 | Notas |
|---|---|---|
language |
languageCode |
Se cambió el nombre. Cuando se omite, la versión 3 usa el encabezado Accept-Language o, de forma predeterminada, en, mientras que la versión 4 usa de forma predeterminada el idioma y la escritura locales de la ubicación. |
region |
regionCode |
Se cambió el nombre. Cuando se omite, la versión 3 se establece de forma predeterminada en us, mientras que la versión 4 no tiene un valor predeterminado. |
result_type |
types |
Se cambió el nombre y se usan parámetros de consulta repetidos. |
location_type |
granularity |
Se cambió el nombre y se usan parámetros de consulta repetidos. |
extra_computations |
Eliminado | Se reemplazó por el método SearchDestinations. |
Cambios en el campo de respuesta
| Campo de v3 | Campo v4 | Notas |
|---|---|---|
status, error_message |
Eliminado | La versión 4 usa códigos de estado HTTP y cuerpos de error. |
results.address_components.long_name/results.address_components.short_name |
results.addressComponents.longText/results.addressComponents.shortText |
Se cambió el nombre. |
results.geometry.location_type |
results.granularity |
Se cambió el nombre. |
results.geometry.location |
results.location |
Nombres de los campos: lat/lng -> latitude/longitude. |
results.geometry.viewport |
results.viewport |
Nombres de los campos: northeast/southwest -> high/low. |
| Nuevo | results.addressComponents.languageCode |
Es el idioma del componente de dirección específico. |
| Nuevo | results.bounds |
Límites explícitos con high/low. |
| Nuevo | results.place |
Es el nombre del recurso del lugar. |
| Nuevo | results.postalAddress |
Objeto PostalAddress estructurado. |
Migra desde los descriptores de direcciones de la versión 3
En la versión 3 de la API de Geocoding, pasar extra_computations=ADDRESS_DESCRIPTORS devolvía un objeto address_descriptor que contenía landmarks[] y areas[]. En la versión 4 de la API de Geocoding, esta función se reemplaza por el método SearchDestinations (POST /v4/geocode/destinations), que devuelve un contexto espacial enriquecido directamente dentro de cada objeto Destination.
En la siguiente tabla, se asignan los campos heredados de la versión 3 de address_descriptor a sus equivalentes de la versión 4 de SearchDestinations:
Campo address_descriptor de v3 |
Campo SearchDestinations de la v4 |
Notas de migración |
|---|---|---|
landmarks[] |
destinations[].landmarks[] |
Solicita destinations.landmarks en tu X-Goog-FieldMask. |
landmarks[].place_id |
landmarks[].place.placeId |
Se une dentro del objeto place (PlaceView). |
landmarks[].display_name |
landmarks[].place.displayName |
Texto localizado (text y languageCode) |
landmarks[].types |
landmarks[].place.types |
Es un array de cadenas de tipos de lugares. |
landmarks[].spatial_relationship |
landmarks[].relationalDescription |
En lugar de un enum sin procesar (ACROSS_THE_ROAD, AROUND_THE_CORNER), la versión 4 devuelve una frase localizada y legible por humanos (p.ej., "Across from Central Park"). |
landmarks[].straight_line_distance_meters |
landmarks[].straightLineDistanceMeters |
Se cambió el nombre a lowerCamelCase. |
landmarks[].travel_distance_meters |
landmarks[].travelDistanceMeters |
Se cambió el nombre a lowerCamelCase. |
areas[] (enum containment) |
destinations[].containingPlaces[] y subDestinations[] |
Equivalente disponible más cercano para la jerarquía estructural: los complejos, campus, centros comerciales y edificios circundantes se devuelven como objetos PlaceView estructurados en containingPlaces[] y subDestinations[] (con structureType establecido en GROUNDS o BUILDING y contornos displayPolygon opcionales). Ten en cuenta que no hay un reemplazo directo 1:1 para las áreas de proximidad de vecindarios o distritos, ni para la enumeración containment de la versión 3 (NEAR, WITHIN, OUTSKIRTS). |
Migra desde la geocodificación de Place de la versión 3
Si usas place_id para obtener la dirección de un ID de lugar específico con Geocoding
v3, debes migrar al método Place
Geocoding de la versión v4, que
acepta una solicitud GET.
La API v4 cambia los nombres, la estructura y la compatibilidad de varios parámetros. Te recomendamos que uses una máscara de campo para especificar los campos que deseas que se muestren en la respuesta.
Cambios en los parámetros de solicitud
| Parámetro de v3 | Parámetro de v4 | Notas |
|---|---|---|
place_id |
Campo place en el proto de solicitud |
Ahora, el ID de lugar se proporciona como un parámetro de ruta places/{place}, por ejemplo: https://geocode.googleapis.com/v4/geocode/places/ChIJj61dQgK6j4AR4GeTYWZsKWw. Esto se asigna al campo de lugar en la solicitud subyacente. |
language |
languageCode |
Se cambió el nombre. Cuando se omite, la versión 3 usa el encabezado Accept-Language o, de forma predeterminada, en, mientras que la versión 4 usa de forma predeterminada el idioma y la escritura locales de la ubicación. |
region |
regionCode |
Se cambió el nombre. Cuando se omite, la versión 3 se establece de forma predeterminada en us, mientras que la versión 4 no tiene un valor predeterminado. |
Cambios en el campo de respuesta
| Campo de v3 | Campo v4 | Notas |
|---|---|---|
status, error_message |
Eliminado | La versión 4 usa códigos de estado HTTP y cuerpos de error. |
results |
(raíz) | La versión 4 devuelve un solo objeto de resultado, no un array results. |
results.address_components.long_name/results.address_components.short_name |
addressComponents.longText/addressComponents.shortText |
Se cambió el nombre. |
results.geometry.location_type |
granularity |
Se cambió el nombre. |
results.geometry.location |
location |
Nombres de los campos: lat/lng -> latitude/longitude. |
results.geometry.viewport |
viewport |
Nombres de los campos: northeast/southwest -> high/low. |
results.postcode_localities |
postalCodeLocalities |
Se cambió el nombre. Ahora se devuelve para una o más localidades (la versión 3 requería más de 1). |
| Nuevo | addressComponents.languageCode |
Es el idioma del componente de dirección específico. |
| Nuevo | bounds |
Límites explícitos con high/low. |
| Nuevo | place |
Es el nombre del recurso del lugar. |
| Nuevo | postalAddress |
Objeto PostalAddress estructurado. |
Migra de Geocoding Hyperlocal Data a Destinations
Las siguientes funciones de la API de Geocoding v3 se reemplazarán por el método SearchDestinations de la API de Geocoding v4:
- Entradas
- Puntos de navegación
- Contornos de edificios
- Terrenos
Si usabas la API de Geocoding v3 para las funciones anteriores, consulta este documento
para usar el método SearchDestinations en su lugar y obtener estas funciones.
En este documento, se explica dónde encontrar estas funciones en la respuesta de SearchDestinations y las diferencias en cómo se representan estas funciones en las respuestas de la API entre la versión 3 de la API de Geocoding y el método SearchDestinations de la versión 4 de la API de Geocoding.
Entradas
Para obtener las entradas asociadas con un destination, usa el campo destination.entrances.
Cada entrance
en destination.entrances tiene los siguientes campos (que reemplazan el esquema buildings.entrances heredado de la versión 3):
displayName: Es un nuevo campo opcional que contiene un nombre legible por humanos para la entrada, por ejemplo,"Gate B".location: Es una ubicación de tipoLatLngque usalatitudeylongitude(reemplaza alat/lngde la versión 3).tags: Es igual al campotagsde las entradas de la API de Geocoding v3 (comoPREFERRED).place: Es el nombre del recurso del lugar (por ejemplo,places/ChIJ...), que reemplaza el campobuilding_place_idde la API de Geocoding v3. En la versión 4, este lugar puede representar cualquier estructura de destino (edificio, campus o parque), no solo un edificio.
Puntos de navegación
Para obtener los puntos de navegación asociados con un destination, usa el campo
destination.navigationPoints.
Cada navigationPoint
en destination.navigationPoints tiene los siguientes campos (que reemplazan el esquema navigation_points heredado de la versión 3):
navigationPointToken: Es una cadena de token encriptada que se usa para enrutar a este punto de navegación específico en el métodoComputeRoutesde la API de Routes (Waypoint.navigationPointToken). Consulta Cómo trazar una ruta con tokens de puntos de navegación.displayName: Es un campo opcional nuevo que contiene un nombre legible por humanos para el punto de navegación, por ejemplo,"5th Ave".location: Es una ubicación de tipoLatLngque usalatitudeylongitude.travelModes: Es similar al camporestricted_travel_modesde la API de Geocoding v3, excepto que la v4 especifica los modos de viaje aceptables (DRIVE,WALK) en lugar de los modos de viaje restringidos.usage: Es un campo nuevo que especifica los casos de uso de llegada admitidos para el punto de navegación (comoPICKUP,DROPOFFoPARKING).
Contornos de edificios
Para obtener los contornos de los edificios asociados con un destination, usa el campo displayPolygon de los objetos placeView en el destination que representan edificios (reemplaza el array buildings.building_outlines heredado de la versión 3). Para cada placeView, verifica si es un edificio con el campo placeView.structureType. Si el tipo de estructura es BUILDING, puedes obtener el contorno del campo placeView.displayPolygon. La placeView también tendrá campos adicionales para el edificio que no estaban en la API de Geocoding v3.
Un destination puede tener un objeto placeView que represente un edificio en los
siguientes campos:
destination.primary: Es el lugar principal del destino.destination.containingPlaces: Es un campo repetido que contiene lugares más grandes que "contienen" el lugar principal. Por ejemplo, si el lugar principal es unsubpremise,containingPlacessuele contener elplaceViewque representa el edificio.destination.subDestinations: Es un campo repetido que contiene subdestinos del lugar principal (por ejemplo, unidades de departamentos o suites individuales dentro de un edificio).
Ten en cuenta que el formato de placeView.displayPolygon coincide con el formato del contorno del edificio en la API de Geocoding v3, que es el formato GeoJSON, con el formato RFC 7946.
Terrenos
Al igual que con los contornos de edificios, para obtener los terrenos asociados con un destination, usa el campo displayPolygon de los objetos placeView en el destination que representan terrenos (reemplazando el array grounds heredado de la versión 3). Para cada placeView, verifica si es un polígono de terreno con el campo placeView.structureType. Si el tipo de estructura es GROUNDS, puedes obtener el contorno del campo placeView.displayPolygon. El placeView también tendrá campos adicionales para los terrenos que no estaban en la API de Geocoding v3.
Un destination puede tener un objeto placeView que represente un terreno en los siguientes campos:
destination.primarydestination.containingPlacesdestination.subDestinations
Ten en cuenta que el formato de placeView.displayPolygon coincide con el formato de contorno de los terrenos en la API de Geocoding v3, que es el formato GeoJSON, con el formato RFC 7946.
Precisión de los resultados
En la API de Geocoding v3, el campo location_type de la geometría de respuesta
indicaba la precisión de los resultados, y algunos clientes clasificaban o filtraban
los resultados en función de estos valores (ROOFTOP, RANGE_INTERPOLATED,
GEOMETRIC_CENTER y APPROXIMATE). En las migraciones estándar de la API de Geocoding v4,
este campo se cambia a granularity.
En la API de Destinations (v4 SearchDestinations), no hay un campo location_type. En cambio, la información espacial se maneja de otra manera:
- No se necesita un filtrado manual del cliente: Si bien la geocodificación estándar proporciona varios resultados con diferentes niveles de detalle, el método
SearchDestinationsminimiza la ambigüedad, ya que resuelve un solo destino optimizado siempre que sea posible. Esto elimina la necesidad de que los clientes filtren por tipo de ubicación para determinar qué resultado es el mejor. - Información espacial representada por el tipo de estructura y los polígonos de visualización:
La geometría y la estructura espaciales se indican de la siguiente manera:
- El
displayPolygon(para la geometría exacta). - El campo
structureTypedentro del objetoplaceView.
- El
- Asignación de tipos de estructura:
- Un
structureTypedePOINT,BUILDINGoSECTIONsuele corresponder a lo que antes se llamabaROOFTOP. - Un
structureTypedeGROUNDSsuele corresponder aGEOMETRIC_CENTER.
- Un
Usa una máscara de campo para solicitar estas funciones
El método SearchDestinations requiere una máscara de campo, como se explica en Elige los campos que se mostrarán. La máscara de campo se puede configurar
en * para que se muestren todos los campos, o puedes configurarla para que se muestren los campos específicos
que deseas recibir. Por ejemplo, la siguiente solicitud a la API establece la máscara de campo para recibir todos los campos necesarios para obtener las entradas, los puntos de navegación, los contornos de los edificios y los terrenos de un 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
Recetas de migración y patrones de código comunes
Cuando migres flujos de trabajo complejos de Geocoding v3 o Geocoding++ a SearchDestinations, usa las siguientes recetas de código para extraer estructuras comunes de direcciones y datos espaciales.
Extrae el mejor polígono de edificio
Si deseas renderizar el perímetro de un edificio para una ubicación o un destino, sigue estos pasos:
- Verifica si el lugar
primarytienestructureType === 'BUILDING'y contiene undisplayPolygon. - De lo contrario, inspecciona
containingPlacespara encontrar el edificio que lo contiene (útil cuando el destino principal es un subdestino de un edificio más grande). - Si no se encuentra ningún edificio que lo contenga, consulta
subDestinationspara ver si se enumeran edificios individuales.
Ejemplo de código de 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
Ejemplo de código de 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; }
Extrae el contorno de los terrenos
Si necesitas el límite de un complejo de departamentos, un campus corporativo, un centro comercial o un parque, sigue estos pasos:
- Si el lugar
primaryrepresenta todo el complejo (structureType === 'GROUNDS'), usaprimary.displayPolygon. - Si el lugar
primaryes un edificio o una entrada que se encuentra dentro de un complejo más grande, busca los terrenos circundantes encontainingPlaces.
Ejemplo de código de 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
Ejemplo de código de 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; }
Selecciona puntos de referencia para mostrar la dirección en comparación con la llegada de última milla
La versión 3 de Geocoding address_descriptor devolvió una enumeración spatial_relationship (WITHIN, BESIDE, BEHIND, NEAR, ACROSS_THE_ROAD, AROUND_THE_CORNER). En SearchDestinations:
- No hay un enum de relación sin procesar. En su lugar, usa
relationalDescription.textdirectamente. Contiene frases localizadas y listas para mostrar, como"Across from Central Park"o"Behind the convention center". No antepongas"Near "de forma manual. - Usa
tagspara seleccionar el punto de referencia adecuado para tu caso de uso:ARRIVAL: Son puntos de referencia hiperlocales situados inmediatamente junto al destino, frente a él o al otro lado de la calle (por lo general, a una distancia de entre 50 y 100 metros). Es ideal para la llegada de conductores en tiempo real, la confirmación de entrega de mensajería o las tarjetas de llegada en la app.ADDRESS: Son puntos de referencia destacados a nivel local dentro del vecindario circundante (por lo general, entre 100 y 500 metros). Es ideal para la confirmación de la compra de cara al cliente, la revisión de pedidos o la desambiguación del destino antes del viaje.- Si un punto de referencia tiene las etiquetas
ADDRESSyARRIVAL, significa que es conocido en el vecindario y que está inmediatamente adyacente al destino.
Ejemplo de código de 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
Ejemplo de código de 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; }
Cómo trazar rutas hacia puntos de navegación de vehículos y entradas preferidas
Los flujos de trabajo de despacho y llegada de última milla combinan dos tipos complementarios de puntos de acceso espacial:
- Navegación paso a paso en auto: Dirige los vehículos a los puntos de llegada designados en la ruta con
navigationPoints. Los puntos de navegación se clasifican previamente por proximidad y relevancia, por lo que el primer candidato con el modo de viaje deseado (como'DRIVE') y la etiqueta de uso (como'DROPOFF'o'PICKUP') proporciona el punto de referencia óptimo para el vehículo. Envía sunavigationPointTokenal métodoComputeRoutes(Waypoint.navigationPointToken) de la API de Routes o al SDK de Navigation. Si no existe un punto de conducción ajustado a la ruta, recurre a la entrada del edificio o al centroide principal. - Acceso físico a la puerta: Guía al mensajero a pie o al pasajero hasta la entrada del edificio con
destinations.entrances. Consultatagspara'PREFERRED'y encuentra entradas que probablemente proporcionen acceso físico directo. Si no hay datos de entrada disponibles, recurre a un punto de navegación peatonal (travelModes, incluido'WALK') o al centroide principal.
Ejemplo de código de 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, }
Ejemplo de código de 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, }; }
Consideraciones de seguridad
La API de Geocoding v4 está diseñada como una API de servidor a servidor. No hay una ruta de migración directa para los usuarios de JavaScript de la versión 3 a la 4. Llamar a los métodos de la versión 4 directamente desde JavaScript del cliente (por ejemplo, en un navegador) con una clave de API expone tu clave de API a un alto riesgo de robo y uso inadecuado.
Las restricciones de URLs de referencia HTTP, si bien son útiles, no son una protección suficiente para los extremos de servicios web, ya que los atacantes pueden omitirlas fácilmente falsificando el encabezado Referer en sus solicitudes.
Enfoque recomendado
La forma recomendada de usar la API de Geocoding v4 es desde tu propio servidor de backend. Tu aplicación cliente debe realizar solicitudes a este servidor intermediario, que, luego, llama de forma segura a la API de Google con una clave de API protegida (por ejemplo, una clave almacenada en una variable de entorno o un Secret Manager). Esto garantiza que tu clave de API nunca se exponga en el código de frontend.
Alternativas para las necesidades del cliente
Si tienes necesidades del cliente que requieren geocodificación, considera usar una de las soluciones existentes del cliente:
- Servicio de Geocoding en la API de Maps JavaScript: El servicio de Geocoding sigue usando el backend de la versión 3 y está diseñado para usarse en un entorno de navegador.
- Kit de IU de Places: Usa el kit de IU de Places, incluidos los elementos de Place Autocomplete, para los elementos de la interfaz de usuario relacionados con las direcciones.