You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter/Dart中如何从Google Maps Place Autocomplete API提取城市与国家名称

解决方案

一、为什么无法直接从Autocomplete响应提取城市/国家

Place Autocomplete API的核心作用是提供输入联想建议,返回的description或structured_formatting仅为格式化展示文本,不包含结构化的地址拆分信息。要获取准确的城市(城镇)和国家名称,必须通过响应返回的place_id调用Place Details API,从返回的address_components字段中提取对应类型的地址组件。

二、修改代码实现提取逻辑

1. 添加Place Details API调用方法

新增方法,用Autocomplete返回的place_id请求详细地址信息:

Future<String?> fetchPlaceDetails(String placeId) async {
  Uri uri = Uri.https(
    "maps.googleapis.com",
    "maps/api/place/details/json",
    {
      "place_id": placeId,
      "fields": "address_components", // 仅请求所需字段,缩减响应体积
      "key": apiKey,
    },
  );
  return await NetworkUtility.fetchUrl(uri);
}

2. 新增地址组件解析模型类

创建用于解析Place Details响应的模型类:

class AddressComponent {
  final String? longName;
  final String? shortName;
  final List<String>? types;

  AddressComponent({this.longName, this.shortName, this.types});

  factory AddressComponent.fromJson(Map<String, dynamic> json) {
    return AddressComponent(
      longName: json['long_name'] as String?,
      shortName: json['short_name'] as String?,
      types: (json['types'] as List?)?.cast<String>(),
    );
  }
}

class PlaceDetailsResponse {
  final String? status;
  final List<AddressComponent>? addressComponents;

  PlaceDetailsResponse({this.status, this.addressComponents});

  factory PlaceDetailsResponse.fromJson(Map<String, dynamic> json) {
    return PlaceDetailsResponse(
      status: json['status'] as String?,
      addressComponents: json['result']?['address_components'] != null
          ? (json['result']['address_components'] as List)
              .map<AddressComponent>((json) => AddressComponent.fromJson(json))
              .toList()
          : null,
    );
  }

  static PlaceDetailsResponse parseDetailsResult(String responseBody) {
    final parsed = json.decode(responseBody).cast<String, dynamic>();
    return PlaceDetailsResponse.fromJson(parsed);
  }
}

3. 提取城市和国家的工具方法

新增方法,从地址组件列表中筛选出目标类型的信息:

Map<String, String?> extractCityAndCountry(List<AddressComponent> components) {
  String? city;
  String? country;

  for (var component in components) {
    if (component.types?.contains('locality') == true) {
      city = component.longName;
    } else if (component.types?.contains('country') == true) {
      country = component.longName;
    }
  }

  return {'city': city, 'country': country};
}

4. 整合到现有流程

在用户选择某个Autocomplete预测结果后,调用上述方法提取信息:

void getPlaceCityAndCountry(AutocompletePrediction prediction) async {
  if (prediction.placeId == null) return;

  final detailsResponse = await fetchPlaceDetails(prediction.placeId!);
  if (detailsResponse != null) {
    PlaceDetailsResponse details = PlaceDetailsResponse.parseDetailsResult(detailsResponse);
    if (details.addressComponents != null) {
      var cityCountry = extractCityAndCountry(details.addressComponents!);
      // 此处可直接使用cityCountry['city']和cityCountry['country']
      print("城市: ${cityCountry['city']}, 国家: ${cityCountry['country']}");
    }
  }
}

三、关于非英语输入的疑问解答

  • 是否为有意设计? 是的。Google Places API会根据用户输入的语言、地区偏好调整格式化文本的展示顺序(比如阿拉伯语等从右到左的语言会将国家放在前面),这是针对不同语言阅读习惯的展示优化。
  • 能否准确提取? 完全可以。无论输入语言是什么,address_components中的每个组件都带有明确的types标签(如locality对应城市、country对应国家),通过类型筛选提取信息不受文本展示顺序影响,能稳定获取准确结果。

内容的提问来源于stack exchange,提问作者boodzadood

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 19:35:45