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
相关产品推荐
相关产品推荐

