Flutter技术求助:如何将JSON数据转为Google Maps地图标记
问题分析与解决方案
核心问题点
你的代码存在三个关键问题导致地图标记无法显示:
- 经纬度类型不匹配:
Shop类中refineWgs84Lat和refineWgs84Logt是String类型,但LatLng构造函数要求传入double类型,直接传递字符串会导致标记位置无效。 - 实体类属性访问错误:构建
Marker时使用了shop['cmpnmNm']这种Map键值访问方式,但shops是List<Shop>实体列表,需直接访问类属性。 - 异步数据加载未处理:若未通过
FutureBuilder等待fetchJson()完成,地图渲染时shops可能为空列表,自然看不到标记。
分步修复
1. 修改Shop类的经纬度类型
将经纬度字段改为double类型,并在fromJson中完成字符串到数值的转换:
class Shop { final String cmpnmNm; // shopname final String indutypeNm; final String sigunNm; final String bsnTmNm; final String provsnProdlstNm; final String bizregno; final String provsnTrgtNm2; final String refineLotnoAddr; final String refineZipno; final double refineWgs84Lat; // 改为double类型 final double refineWgs84Logt; // 改为double类型 final String detailAddr; final String provsnTrgtNm1; final String refineRoadnmAddr; Shop({ required this.cmpnmNm, required this.indutypeNm, required this.sigunNm, required this.bsnTmNm, required this.provsnProdlstNm, required this.bizregno, required this.provsnTrgtNm2, required this.refineLotnoAddr, required this.refineZipno, required this.refineWgs84Lat, required this.refineWgs84Logt, required this.detailAddr, required this.provsnTrgtNm1, required this.refineRoadnmAddr, }); Shop.fromJson(Map<String, dynamic> json) : cmpnmNm=json["CMPNM_NM"] as String, indutypeNm= json["INDUTYPE_NM"] as String, sigunNm= json["SIGUN_NM"] as String, bsnTmNm= json["BSN_TM_NM"] as String, provsnProdlstNm= json["PROVSN_PRODLST_NM"] as String, bizregno= json["BIZREGNO"] as String, provsnTrgtNm2= json["PROVSN_TRGT_NM2"] as String, refineLotnoAddr= json["REFINE_LOTNO_ADDR"] as String, refineZipno= json["REFINE_ZIPNO"] as String, // 转换字符串为double,兼容空值情况 refineWgs84Lat= double.tryParse(json["REFINE_WGS84_LAT"] as String) ?? 0.0, refineWgs84Logt= double.tryParse(json["REFINE_WGS84_LOGT"] as String) ?? 0.0, detailAddr= json["DETAIL_ADDR"] as String, provsnTrgtNm1= json["PROVSN_TRGT_NM1"] as String, refineRoadnmAddr= json["REFINE_ROADNM_ADDR"] as String; Map<String, dynamic> toJson() => { "CMPNM_NM": cmpnmNm, "INDUTYPE_NM": indutypeNm, "SIGUN_NM": sigunNm, "BSN_TM_NM": bsnTmNm, "PROVSN_PRODLST_NM": provsnProdlstNm, "BIZREGNO": bizregno, "PROVSN_TRGT_NM2": provsnTrgtNm2, "REFINE_LOTNO_ADDR": refineLotnoAddr, "REFINE_ZIPNO": refineZipno, "REFINE_WGS84_LAT": refineWgs84Lat.toString(), "REFINE_WGS84_LOGT": refineWgs84Logt.toString(), "DETAIL_ADDR": detailAddr, "PROVSN_TRGT_NM1": provsnTrgtNm1, "REFINE_ROADNM_ADDR": refineRoadnmAddr }; }
2. 修正Google Map的Marker构建代码
直接访问Shop类的属性,替代Map键值访问方式:
GoogleMap( initialCameraPosition: CameraPosition( target: LatLng(37.532600, 127.024612), zoom: 18, ), markers: Set<Marker>.of(shops.map((shop) { return Marker( markerId: MarkerId(shop.cmpnmNm), position: LatLng(shop.refineWgs84Lat, shop.refineWgs84Logt), infoWindow: InfoWindow(title: shop.cmpnmNm), ); })), )
3. 确保异步数据正确加载
使用FutureBuilder等待接口请求完成后再渲染地图:
// 页面Widget中替换原GoogleMap的渲染逻辑 FutureBuilder<List<Shop>>( future: fetchJson(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } else if (snapshot.hasError) { return Center(child: Text('加载失败: ${snapshot.error}')); } else if (!snapshot.hasData || snapshot.data!.isEmpty) { return const Center(child: Text('没有店铺数据')); } else { final shops = snapshot.data!; return GoogleMap( initialCameraPosition: CameraPosition( target: LatLng(37.532600, 127.024612), zoom: 18, ), markers: Set<Marker>.of(shops.map((shop) { return Marker( markerId: MarkerId(shop.cmpnmNm), position: LatLng(shop.refineWgs84Lat, shop.refineWgs84Logt), infoWindow: InfoWindow(title: shop.cmpnmNm), ); })), ); } }, )
额外检查点
- 确认API返回的经纬度是有效的数值字符串,无空值或非数字内容。
- 检查Google Map API密钥是否在Android/iOS配置文件中正确设置。
- 若店铺位置不在初始相机范围内,可调整初始缩放比例或自动计算包含所有标记的相机边界。
内容的提问来源于stack exchange,提问作者이유림
相关产品推荐
相关产品推荐

