Migra de Geocoding v3 a v4

Desarrolladores del Espacio Económico Europeo (EEE)

La API de Geocoding v4 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 la 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 API de Geocoding v3

Si usas la versión 3 de Geocoding para geocodificar direcciones, debes migrar al método Geocode an address de la versión 4, que acepta una solicitud GET.

La API v4 cambia los nombres, la estructura y la compatibilidad con 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 la solicitud

Parámetro de la versión 3 Parámetro de la versión 4 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 (v3 components) se pueden pasar como parámetros de consulta address.*. Consulta Cómo reproducir filtros de componentes de la versión 3.
bounds locationBias.rectangle Se cambió el nombre y la estructura a objeto.
language languageCode Se cambió el nombre.
region regionCode Se cambió el nombre.
extra_computations Eliminado Se reemplazó por el método SearchDestinations.

Cambios en los campos de respuesta

Campo de v3 Campo de 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 (se requiere la versión 3 > 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 la versión 3 de la API de Geocoding incluía un parámetro components que permitía filtrar de forma estricta los resultados para componentes específicos (p.ej., components=country:US). La Geocodificación directa en la versión 4 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 de escritura 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 a los filtros de componentes fijos de la versión 3, debes implementar el filtrado del cliente en el array results que devuelve 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 en otros campos, ya que no existen criterios de filtrado confiables.

Filtrar por país

Compara 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 tu 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

Compara 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 tu 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 los códigos 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 puede representarse 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 una coincidencia en postalAddress.administrativeArea y 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

Compara 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 espacios y guiones, y convertir a un caso coherente.

Es posible que se necesite una normalización más avanzada para controlar los prefijos (p. ej., "L2" en el Reino Unido) o los sufijos (p. ej., "+4" en los códigos postales de EE.UU.) de los códigos postales. 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 segmentas.

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 devuelve 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 códigos postales 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 API de Geocoding inversa v3

Si usas la versión 3 de la geocodificación inversa para convertir coordenadas en direcciones, debes migrar al método de la versión 4 Geocodificación inversa de una ubicación, que acepta una solicitud GET.

La API v4 cambia los nombres, la estructura y la compatibilidad con 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 la solicitud

Parámetro de la versión 3 Parámetro de la versión 4 Notas
language languageCode Se cambió el nombre.
region regionCode Se cambió el nombre.
result_type types Se cambió el nombre; usa parámetros de consulta repetidos.
location_type granularity Se cambió el nombre; usa parámetros de consulta repetidos.
extra_computations Eliminado Se reemplazó por el método SearchDestinations.

Cambios en los campos de respuesta

Campo de v3 Campo de 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

Si usas address_descriptor para obtener información adicional sobre una ubicación con Geocoding v3, debes migrar al uso del campo landmarks de SearchDestinationsResponse.

Migra desde la versión 3 de Place Geocoding

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 4, que acepta una solicitud GET.

La API v4 cambia los nombres, la estructura y la compatibilidad con 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 la solicitud

Parámetro de la versión 3 Parámetro de la versión 4 Notas
place_id Campo place en el proto de solicitud El ID de lugar ahora se proporciona como un parámetro de ruta places/{place}, por ejemplo: https://geocode.googleapis.com/v4/geocode/places/ChIJj61dQgK6j4AR4GeTYWZsKWw. Este campo se asigna al campo de lugar en la solicitud subyacente.
language languageCode Se cambió el nombre.
region regionCode Se cambió el nombre.

Cambios en los campos de respuesta

Campo de v3 Campo de v4 Notas
status, error_message Eliminado La versión 4 usa códigos de estado HTTP y cuerpos de error.
results (root) 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 (se requiere la versión 3 > 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 datos hiperlocales de Geocoding a destinos

Las siguientes funciones de la API de Geocoding v3 se reemplazan 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, usa este documento para obtener ayuda y usar el método SearchDestinations en su lugar. En este documento, se explica dónde encontrar estas características en la respuesta de SearchDestinations y las diferencias en la forma en que se representan estas características en las respuestas de la API entre la API de Geocoding v3 y el método SearchDestinations de la API de Geocoding v4.

Entradas

Para obtener las entradas asociadas a un destination, usa el campo destination.entrances.

Ten en cuenta que el formato de un entrance es ligeramente diferente del formato de entrada en la versión 3 de la API de Geocoding. Cada entrada en destination.entrances tiene los siguientes campos:

  • displayName: Es un nuevo campo opcional que tendrá un nombre legible para la entrada, por ejemplo, "Puerta B".
  • location: Es una ubicación de tipo LatLng, que es diferente del formato que se usa en la API de Geocoding v3.
  • tags: Es igual que el campo tags de las entradas de la API de Geocoding v3.
  • place: Es análogo al campo buildingPlaceId de las entradas de la API de Geocoding v3. Sin embargo, el ID de lugar en este campo podría ser para un lugar de cualquier tipo, no necesariamente solo un edificio.

Para obtener los puntos de navegación asociados con un destination, usa el campo destination.navigationPoints.

Ten en cuenta que el formato de un navigationPoint es ligeramente diferente del formato de punto de navegación en la API de Geocoding v3. Cada punto de navegación en destination.navigationPoints tiene los siguientes campos:

  • displayName: Es un nuevo campo opcional que tendrá un nombre legible para el punto de navegación, por ejemplo, "5th Ave".
  • location: Es una ubicación de tipo LatLng, que es diferente del formato que se usa en la API de Geocoding v3.
  • travelModes: Es similar al campo restrictedTravelModes de los puntos de navegación de la API de Geocoding v3. Los valores de enumeración posibles son los mismos. La única diferencia es que este campo ahora representa los modos de viaje aceptables para el punto de navegación, en lugar de los modos de viaje restringidos.
  • usage: Es un campo nuevo que contiene los casos de uso admitidos por el punto de navegación. Ten en cuenta que la mayoría de los puntos de navegación tendrán un uso de UNKNOWN, pero eso no significa necesariamente que el uso del punto de navegación esté restringido de alguna manera.

Contornos de edificios

Para obtener los contornos de los edificios asociados a un objeto destination, debes usar el campo displayPolygon de los objetos placeView en el objeto destination que representan edificios. Para cada placeView, puedes verificar si es un edificio con el campo placeView.structureType. Si el tipo de estructura es BUILDING, puedes obtener el esquema del campo placeView.displayPolygon. El objeto placeView también tendrá campos adicionales para el edificio que no estaban en la API de Geocoding v3.

Un objeto 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 puede contener lugares más grandes que "contienen" el lugar principal. Por ejemplo, si el lugar principal es un subpremise, containingPlaces suele contener el placeView que representa el edificio.
  • destination.subDestinations: Es un campo repetido que puede contener subdestinos del lugar principal. Por ejemplo, las unidades de departamentos individuales de un edificio. Por lo general, este campo no tendrá un placeView que represente un edificio.

Ten en cuenta que el formato de placeView.displayPolygon coincide con el formato de contorno de la estructura en la API de Geocoding v3, que es el formato GeoJSON, con el formato RFC 7946.

Terrenos

Al igual que con los esquemas de edificios, para obtener los terrenos asociados a un destination, debes usar el campo displayPolygon de los objetos placeView en el destination que representan terrenos. Para cada placeView, puedes verificar si es un motivo con el campo placeView.structureType. Si el tipo de estructura es GROUNDS, puedes obtener el esquema del campo placeView.displayPolygon. El objeto placeView también tendrá campos adicionales para los motivos que no estaban en la API de Geocoding v3.

Un objeto destination puede tener un objeto placeView que represente un motivo en los siguientes campos:

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

Ten en cuenta que el formato de placeView.displayPolygon coincide con el formato de esquema de la base 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 en la geometría de la respuesta indicaba la precisión de los resultados, y algunos clientes clasificaban o filtraban los resultados según estos valores (ROOFTOP, RANGE_INTERPOLATED, GEOMETRIC_CENTER y APPROXIMATE). En las migraciones estándar de la API de Geocoding v4, este campo se renombró como granularity.

En la API de Destinations (v4 SearchDestinations), no hay ningún campo location_type. En cambio, la información espacial se maneja de otra manera:

  • No se necesita filtrado manual del cliente: Si bien la API de Geocoding estándar proporciona varios resultados con diferentes niveles de detalle, el método SearchDestinations minimiza la ambigüedad, ya que resuelve una sola ubicación de destino optimizada 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 structureType dentro del objeto placeView.
  • Asignación de tipos de estructura:
    • Un structureType de POINT, BUILDING o SECTION generalmente corresponde a lo que antes se llamaba ROOFTOP.
    • Un structureType de GROUNDS generalmente corresponde a GEOMETRIC_CENTER.

Usa una máscara de campo para solicitar estas funciones

El método SearchDestinations requiere una máscara de campo, como se explica en Cómo elegir los campos que se devolverán. La máscara de campo se puede establecer en * para devolver todos los campos, o bien puedes establecerla en 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 esquemas de 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

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 de la versión 3 a la 4 para los usuarios de JavaScript. 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.

Si bien las restricciones de URL de referencia HTTP son útiles, no son una protección suficiente para los extremos de los servicios web, ya que los atacantes pueden eludirlas fácilmente falsificando el encabezado Referer en sus solicitudes.

La forma recomendada de usar la versión 4 de la API de Geocoding 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 administrador de secretos). 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 lado del cliente que requieren geocodificación, considera usar una de las soluciones existentes del lado del cliente:

  • Servicio Geocoding en la API de Maps JavaScript: El servicio Geocoding sigue usando el backend de la versión 3 y está diseñado para usarse en un entorno de navegador.
  • Places UI Kit: Usa el Places UI Kit, incluidos los elementos de Place Autocomplete, para los elementos de la interfaz de usuario relacionados con la dirección.