Search code examples
flutterapidartgetflutter-getx

Exception has occurred. _TypeError (type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'List<dynamic>') in flutter using getx


I AM TRYTING TO GET LIST OF ALL ITEMS FROM REST API USING GETX BUT THIS ERROR IS BEING THROWN ON FORM LOAD "Exception has occurred. _TypeError (type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'List')" I DON'T KNOW WHY

HERE IS MY MODEL FILE

import 'dart:convert';
import 'package:foodello/model/ShowListing.dart';
import 'package:http/http.dart' as http;

class ApiManager {
  static Future getShowList() async {
    String baseURL = 'https://westmarket.herokuapp.com/api/v1';
    String userId = '62f4ecf82b6e81e77059b332';
    String url = baseURL + '/user/:$userId/products';
    final response = await http.get(Uri.parse(url));
    List jsonResponse = json.decode(response.body);
    return jsonResponse.map((item) => ShowList.fromJson(item)).toList();
  }
}

HERE IS MY API FILE

import 'dart:ffi';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:foodello/model/ShowListing.dart';
import 'package:get/get.dart';
import 'package:foodello/services/apiManager.dart';

class HomeController extends GetxController {
  var showlist = <ShowList>[].obs;

  @override
  void onInit() {
    fetchShowList();
    super.onInit();
  }

  void fetchShowList() async {
    var post = ApiManager.getShowList();
    if (post != null) {
      showlist.value = await post;
    }
  }
}

HERE IS MY HOME PAGE WHERE I'M CALLING THE DATA

        Obx(
          () => Expanded(
            child: ListView.builder(
              itemCount: controller.showlist.length,
              itemBuilder: (BuildContext context, index) {
                var singlePost = controller.showlist[index];
                return Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    Container(
                      height: 200,
                      width: 100,
                      child: Column(
                        children: [
                          Text(singlePost.products.data[index].name),
                          Text(singlePost.products.data[index].price
                              .toString()),
                          Text(singlePost
                              .products.data[index].initialQuantity
                              .toString()),
                          Text(singlePost.products.data[index].soldQuantity
                              .toString()),
                        ],
                      ),




import 'dart:convert';

ShowList showListFromJson(String str) => ShowList.fromJson(json.decode(str));

String showListToJson(ShowList data) => json.encode(data.toJson());

class ShowList {
  ShowList({
    required this.products,
  });

  Products products;

  factory ShowList.fromJson(Map<String, dynamic> json) => ShowList(
        products: Products.fromJson(json["products"]),
      );

  Map<String, dynamic> toJson() => {
        "products": products.toJson(),
      };
}

class Products {
  Products({
    required this.message,
    required this.success,
    required this.statusCode,
    required this.data,
  });

  String message;
  bool success;
  int statusCode;
  List<Datum> data;

  factory Products.fromJson(Map<String, dynamic> json) => Products(
        message: json["message"],
        success: json["success"],
        statusCode: json["statusCode"],
        data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
      );

  Map<String, dynamic> toJson() => {
        "message": message,
        "success": success,
        "statusCode": statusCode,
        "data": List<dynamic>.from(data.map((x) => x.toJson())),
      };
}

class Datum {
  Datum({
    required this.id,
    required this.name,
    required this.price,
    required this.initialQuantity,
    required this.soldQuantity,
    required this.createdAt,
    required this.updatedAt,
    required this.v,
  });

  String id;
  String name;
  int price;
  int initialQuantity;
  int soldQuantity;
  DateTime createdAt;
  DateTime updatedAt;
  int v;

  factory Datum.fromJson(Map<String, dynamic> json) => Datum(
        id: json["_id"],
        name: json["name"],
        price: json["price"],
        initialQuantity: json["initialQuantity"],
        soldQuantity: json["soldQuantity"],
        createdAt: DateTime.parse(json["createdAt"]),
        updatedAt: DateTime.parse(json["updatedAt"]),
        v: json["__v"],
      );

  Map<String, dynamic> toJson() => {
        "_id": id,
        "name": name,
        "price": price,
        "initialQuantity": initialQuantity,
        "soldQuantity": soldQuantity,
        "createdAt": createdAt.toIso8601String(),
        "updatedAt": updatedAt.toIso8601String(),
        "__v": v,
      };
}

Solution

  • The error means the api is returning a map instead of the list your are expecting, so the first thing you have to do is to print your response.body to be sure of whats coming from the api

    I have tested the api it seems the message it's returning is this:

    {
      "result": "Unauthorized, Access Denied",
      "status": 401
    }
    

    which means the api is missing an authorization token so try this:

    static Future getShowList() async {
        try {
           String baseURL = 'https://westmarket.herokuapp.com/api/v1';
           String userId = '62f4ecf82b6e81e77059b332';
           String url = baseURL + '/user/:$userId/products';
           final response = await http.get(
             Uri.parse(url),
             headers: {
               'Authorization': '<your token>'
             },
           );
           
           if(response.statusCode == HttpStatus.ok) {
             List jsonResponse = json.decode(response.body);
             return jsonResponse.map((item) => 
             ShowList.fromJson(item)).toList();
           } else {
             //throw/return an error here
           }
        } catch(e) {
           // throw/return an error here
        }
      }