Flutter调用Google Nearby Search API生成Marker遇类型转换错误
解决Flutter中Google Nearby Search API JSON转换类型不匹配问题
问题核心
你碰到的type '_Map<String, dynamic>' is not a subtype of type 'String'错误,本质是JSON解析时把嵌套的Map类型数据错误赋值给了String类型变量,大概率出在解析地点经纬度(geometry.location)这类嵌套字段的环节。
分步排查与解决
1. 先明确API返回的JSON结构
先确认Google Nearby Search API返回的核心结构(以标准响应为例):
{ "results": [ { "geometry": { "location": { "lat": 37.7749, "lng": -122.4194 } }, "name": "Sample Place", "vicinity": "Sample Address" } ] }
注意geometry.location是嵌套的Map对象,不是字符串。
2. 定义正确的数据模型类
没有匹配的模型类,直接解析JSON很容易踩类型坑,先写对应模型:
class NearbyPlace { final double lat; final double lng; final String name; final String vicinity; NearbyPlace({ required this.lat, required this.lng, required this.name, required this.vicinity, }); // 从JSON解析的工厂方法 factory NearbyPlace.fromJson(Map<String, dynamic> json) { return NearbyPlace( lat: json['geometry']['location']['lat'] as double, lng: json['geometry']['location']['lng'] as double, name: json['name'] as String, vicinity: json['vicinity'] as String, ); } }
⚠️ 重点:别尝试把json['geometry']或json['geometry']['location']直接赋值给String变量,必须深入到lat和lng字段提取数值。
3. 修正HttpRepository的解析逻辑
检查你的HttpRepository实现,确保解析响应时正确处理嵌套字段:
// 假设你的HttpRepository中有这样的请求方法 Future<List<NearbyPlace>> fetchNearbyPlaces(String url) async { final response = await http.get(Uri.parse(url)); if (response.statusCode == 200) { final Map<String, dynamic> data = json.decode(response.body); final List<dynamic> results = data['results']; // 转换为NearbyPlace列表 return results.map((placeJson) => NearbyPlace.fromJson(placeJson)).toList(); } else { throw Exception('加载周边地点失败'); } }
如果之前代码里错误把某个Map字段(比如geometry)赋值给String,这里必须修正。
4. 调整NearbyMosquesController的Marker创建逻辑
在GetX控制器中,确保从NearbyPlace实例提取经纬度生成Marker:
class NearbyMosquesController extends GetxController { final RxList<Marker> markers = <Marker>[].obs; final HttpRepository httpRepo; NearbyMosquesController({required this.httpRepo}); Future<void> loadNearbyMosques() async { try { final places = await httpRepo.fetchNearbyPlaces(YOUR_API_URL); markers.clear(); for (var place in places) { markers.add( Marker( markerId: MarkerId(place.name), position: LatLng(place.lat, place.lng), infoWindow: InfoWindow( title: place.name, snippet: place.vicinity, ), ), ); } } catch (e) { print('生成Marker出错: $e'); } } }
⚠️ 别直接从原始JSON里提取location时把Map当成String用,必须通过模型类解析后再拿数值。
5. 常见错误排查点
- 检查是否写过类似
String location = json['geometry']['location'];的代码,这是典型错误,因为location是Map不是String。 - 确保所有JSON字段类型匹配:比如
lat/lng是double类型,别用int接收;name/vicinity是String类型,别用Map接收。 - 如果用自动生成的模型类(比如json_serializable),检查注解是否正确,嵌套字段是否被正确解析。
快速验证方法
解析JSON时加打印语句,确认字段类型:
print(json['geometry']['location'].runtimeType); // 应该输出 _Map<String, dynamic> print(json['geometry']['location']['lat'].runtimeType); // 应该输出 double
这样能快速定位哪个字段的类型处理出错。
内容的提问来源于stack exchange,提问作者haker man
相关产品推荐
相关产品推荐

