Flutter中解决API返回列表时List与Map类型不匹配错误
问题:Flutter调用API获取列表响应时类型不匹配错误
错误信息
'List' is not a subtype of type 'FutureOr<Map<String, dynamic>>'
现有代码与数据
API Client代码
class ApiClient extends ServiceAPI { final http.Client httpClient; ApiClient({ required this.httpClient, }); Future<Map<String, dynamic>> callApi(Map<String, String> headers, String body, String apiname, Method method) async { // SmartDialog.showLoading(); final url = baseUrl + domainPath + apiname; debugPrint(method.name + " : " + url); debugPrint("HEADER : " + headers.toString()); debugPrint("BODY : " + body); http.Response response; switch (method) { case Method.GET: response = await httpClient.get(Uri.parse(url), headers: headers); break; case Method.POST: response = await httpClient.post(Uri.parse(url), headers: headers, body: body); break; case Method.PUT: response = await httpClient.put(Uri.parse(url), headers: headers, body: body); break; case Method.DELETE: response = await httpClient.delete(Uri.parse(url), headers: headers, body: body); break; } log("RESPONSE : " + response.body); // SmartDialog.dismiss(); if (response.statusCode != 200) { try { throw Exception(json.decode(response.body)['errors'][0]['msg']); } catch (e) { throw Exception(json.decode(response.body)['error']); } } return jsonDecode(response.body); } @override Future<List<AandCDelivery>> completedDelivery() async { var headers = apiheaderWithToken; final body = json.encode({}); return AandCDelivery.fromJson( await callApi(headers, body, completedDeliveries, Method.GET)) as List<AandCDelivery>; } }
API响应数据(修正后合法JSON)
[{"_id":"62e8a1351ae33236c9d75883","delivery_category_id":"62e7806795373a695265fcac","delivery_category_name":"Electronics","delivery_product_id":"62e78292320b04ecc835c755","delivery_product_name":"Mobiles","delivery_id":"62e7ea5a2e72b4ca7505a116","user_name":"Kevin","user_phone_no":"+918870457970","user_picture":"https://www.gravatar.com/avatar/866d2a555baadfb4087796588b2deac7?s=200&r=pg&d=mm","weight":"1","order_no":"EZY-41DRLE3RWL6AVNRBM"}]
Model类代码
List<AandCDelivery> aandCDeliveryFromJson(String str) => List<AandCDelivery>.from( json.decode(str).map((x) => AandCDelivery.fromJson(x))); String aandCDeliveryToJson(List<AandCDelivery> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson()))); class AandCDelivery { AandCDelivery({ this.id, this.deliveryCategoryId, this.deliveryCategoryName, this.deliveryProductId, this.deliveryProductName, this.deliveryId, this.userName, this.userPhoneNo, this.userPicture, this.weight, this.orderNo, }); String? id; String? deliveryCategoryId; String? deliveryCategoryName; String? deliveryProductId; String? deliveryProductName; String? deliveryId; String? userName; String? userPhoneNo; String? userPicture; String? weight; String? orderNo; factory AandCDelivery.fromJson(Map<String, dynamic> json) => AandCDelivery( id: json["_id"], deliveryCategoryId: json["delivery_category_id"], deliveryCategoryName: json["delivery_category_name"], deliveryProductId: json["delivery_product_id"], deliveryProductName: json["delivery_product_name"], deliveryId: json["delivery_id"], userName: json["user_name"], userPhoneNo: json["user_phone_no"], userPicture: json["user_picture"], weight: json["weight"], orderNo: json["order_no"], ); Map<String, dynamic> toJson() => { "_id": id, "delivery_category_id": deliveryCategoryId, "delivery_category_name": deliveryCategoryName, "delivery_product_id": deliveryProductId, "delivery_product_name": deliveryProductName, "delivery_id": deliveryId, "user_name": userName, "user_phone_no": userPhoneNo, "user_picture": userPicture, "weight": weight, "order_no": orderNo, }; }
问题原因
callApi返回类型不匹配:该方法声明返回Future<Map<String, dynamic>>,但实际API响应是JSON数组(List类型),解析后返回的List与方法声明的Map类型冲突,直接触发类型转换错误。completedDelivery解析逻辑错误:误用单个对象的解析方法AandCDelivery.fromJson()处理整个列表响应,再强行转为List<AandCDelivery>,逻辑完全错误,应该使用Model类提供的aandCDeliveryFromJson方法处理列表。
解决方案
方案1:修改callApi支持多类型返回(灵活适配)
将callApi的返回类型改为Future<dynamic>,兼容Map和List类型:
Future<dynamic> callApi(Map<String, String> headers, String body, String apiname, Method method) async { // 原有逻辑保持不变,最后返回jsonDecode(response.body)即可 }
然后修正completedDelivery的解析逻辑:
@override Future<List<AandCDelivery>> completedDelivery() async { var headers = apiheaderWithToken; final body = json.encode({}); // 获取响应并转为List类型 final responseList = await callApi(headers, body, completedDeliveries, Method.GET) as List; // 遍历列表转换为实体类 return responseList.map((item) => AandCDelivery.fromJson(item)).toList(); // 或者直接使用Model类的列表解析方法: // return aandCDeliveryFromJson(json.encode(responseList)); }
方案2:新增列表专用API方法(保持原有方法严谨性)
如果不想修改原有callApi,可以新增一个处理列表的方法:
Future<List<dynamic>> callListApi(Map<String, String> headers, String body, String apiname, Method method) async { final response = await callApi(headers, body, apiname, method); return response as List<dynamic>; }
再修改completedDelivery:
@override Future<List<AandCDelivery>> completedDelivery() async { var headers = apiheaderWithToken; final body = json.encode({}); final listData = await callListApi(headers, body, completedDeliveries, Method.GET); return listData.map((item) => AandCDelivery.fromJson(item)).toList(); }
额外注意事项
- 确保API响应是合法JSON格式,原响应末尾多了两个
}],需要后端修正或前端解析前处理,否则会导致JSON解析失败。 - 禁止强行进行不合理的类型转换,比如用单个对象解析方法处理列表,这类写法必然报错。
内容的提问来源于stack exchange,提问作者Madhanavel
相关产品推荐
相关产品推荐

