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

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,
      
      };
}

问题原因

  1. callApi返回类型不匹配:该方法声明返回Future<Map<String, dynamic>>,但实际API响应是JSON数组(List类型),解析后返回的List与方法声明的Map类型冲突,直接触发类型转换错误。
  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 19:55:16