how to return list of api response values in flutter

Viewed 49
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) {
      // WidgetsBinding.instance.addPostFrameCallback((_) {
      //   ScaffoldMessenger.of(context)
      //       .showSnackBar(SnackBar(content: Text("No data available")));
      // });
      // SmartDialog.showToast(response.body);

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

error: 'List' is not a subtype of type 'FutureOr<Map<String, dynamic>>'

API response:

[{"_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 class:

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

I'm getting list of values as a API response, while returning it I'm getting an error. How to clear 'List' is not a subtype of type 'FutureOr<Map<String, dynamic>>' error. ................................................................

1 Answers

An Api response actually look like the following way:

{
  "data": [{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON:API paints my bikeshed!",
      "body": "The shortest article. Ever.",
      "created": "2015-05-22T14:56:29.000Z",
      "updated": "2015-05-22T14:56:28.000Z"
    },
    "relationships": {
      "author": {
        "data": {"id": "42", "type": "people"}
      }
    }
  }],
  "included": [
    {
      "type": "people",
      "id": "42",
      "attributes": {
        "name": "John",
        "age": 80,
        "gender": "male"
      }
    }
  ]
}

The given example is a Map. So it is of Type Map<String, dynamic>


The response that you have given is:

[{"_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"}]}]

Here the Api response is coming as a List. When you try to call AandCDelivery.fromJson function from the model class, you can see that the parameter of that function is Map<String, dynamic> json.

What you are trying to do is passing a List to fromJson which has parameter as Map.

The fix to this can be done by, sending every items in the List to fromJson and storing the returning object to another List.

final _response = await callApi(headers, body, completedDeliveries, Method.GET);

List<AandCDelivery> response = 
     List<AandCDelivery>.from(_response.map((x) => AandCDelivery.fromJson(x)));

Please verify this code for any mistakes. I had encountered this issue once. I am not sure if the same issue happened to you. What striked me was the 'List' is not a subtype of type 'FutureOr<Map<String, dynamic>>' error.

Also, keep in mind to change the return type of callApi from Future<Map<String, dynamic>> to simply Future, as the response is a list.

Related