skip to Main Content

I’m working on a Flutter app that fetches product data from an API and displays it in a ListView. Here’s an example of the JSON response from the API:

{
    "name": "Watches",
    "products": [
        {
            "id": 88,
            "productName": "Fastrack Men Analogue Plastic White Watch",
            "productDescription": "Stylish and comfortable...",
            "unitPrice": 595,
            "color": "White",
            "categoryName": "Watches",
            "supplierHandle": "[email protected]",
            "pictures": [
                {
                    "front": "http://assets.myntassets.com/v1/images/style/properties/a7eedd8a980535da415d245c91a1f6b0_images.jpg",
                    "back": "http://assets.myntassets.com/v1/images/style/properties/5c5ac4069fff01e25309e7bc7fa85a2b_images.jpg"
                }
            ]
        },
        {
            "id": 89,
            "productName": "Fastrack Men Analogue Grey Watch",
            "productDescription": "Stylish and comfortable...",
            "unitPrice": 595,
            "color": "Grey",
            "categoryName": "Watches",
            "supplierHandle": "[email protected]",
            "pictures": [
                {
                    "front": "http://assets.myntassets.com/v1/images/style/properties/74fc60bd496cca1714d4ced3efb65aff_images.jpg",
                    "back": "http://assets.myntassets.com/v1/images/style/properties/a64b91da98f6274e9aabffd1fbc2eaa4_images.jpg"
                }
            ]
        }
    ]
}

I have a model class and a service class to handle this data. Here is my ProductItem model:

class ProductItem {
  final int id;
  final String productName;
  final String productDescription;
  final int unitPrice;
  final String color;
  final String categoryName;
  final String supplierHandle;
  final String frontImage;
  final String? backImage;

  ProductItem({
    required this.id,
    required this.productName,
    required this.productDescription,
    required this.unitPrice,
    required this.color,
    required this.categoryName,
    required this.supplierHandle,
    required this.frontImage,
    this.backImage,
  });

  factory ProductItem.fromJson(Map<String, dynamic> json) {
    return ProductItem(
      id: json['id'],
      productName: json['productName'],
      productDescription: json['productDescription'],
      unitPrice: json['unitPrice'],
      color: json['color'],
      categoryName: json['categoryName'],
      supplierHandle: json['supplierHandle'],
      frontImage: json['pictures'][0]['front'],
      backImage: json['pictures'][0]['back'],
    );
  }
}

And here is my WatchesCategoryService class:

import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:on_budget/src/modules/customer_modules/home/data/models/products_by_category.dart';
import 'package:on_budget/src/utils/helper/constants/api.dart';

class WatchesCategoryService {
  Future<List<ProductItem>> getWatchesCategoryService() async {
    try {
      final response = await http.get(
        Uri.parse(HomeApi().getWatchesCategoryProducts),
        headers: {'Accept': 'text/plain'},
      );

      if (response.statusCode == 200) {
        final jsonResponse = jsonDecode(response.body);
        List<ProductItem> productsList = [];
        for (var item in jsonResponse['products']) {
          productsList.add(ProductItem.fromJson(item));
        }
        return productsList;
      } else {
        throw Exception('Failed to load products');
      }
    } catch (e) {
      throw Exception('Error fetching data: $e');
    }
  }
}

When I run my code, I encounter the following exception:

Exception: Error fetching data: type '(dynamic) => ProductItem' is not a subtype of type '(String, dynamic) => MapEntry<dynamic, dynamic>' of 'transform'

2

Answers


  1. Chosen as BEST ANSWER

    I tried your code but got this exception, so what's the paroblem?

    enter image description here

    enter image description here

    enter image description here


  2. the issue is coming from where you trying to pass the fetched Json data directly to ProductItem model directly without mapping it.

    try this:

    import 'dart:convert';
    import 'package:http/http.dart' as http;
    import 'package:on_budget/src/modules/customer_modules/home/data/models/products_by_category.dart';
    import 'package:on_budget/src/utils/helper/constants/api.dart';
    
    class WatchesCategoryService {
      Future<List<ProductItem>> getWatchesCategoryService() async {
        try {
          final response = await http.get(
            Uri.parse(HomeApi().getWatchesCategoryProducts),
            headers: {'Accept': 'text/plain'},
          );
    
          if (response.statusCode == 200) {
            final jsonResponse = jsonDecode(response.body);
            //map the data you fetch from Json, pass it to ProductItem.fromJson(), and convert it to list here
            List<ProductItem> productsList = (jsonResponse['products'] as List)
                .map((item) => ProductItem.fromJson(item))
                .toList();
            return productsList;
          } else {
            throw Exception('Failed to load products');
          }
        } catch (e) {
          throw Exception('Error fetching data: $e');
        }
      }
    }
    

    Edit:

    The error message

    "NoSuchMethodError: The method ‘[]’ was called on null"

    indicates that your code is attempting to access a property on a null object. This usually happens when the JSON response does not have the expected structure, or when the key you are trying to access does not exist.

    please do the following to log the Json response on console to see whether there is a null value in there

      if (response.statusCode == 200) {
        final jsonResponse = jsonDecode(response.body);
        // Log the JSON response for debugging
        print('JSON Response: $jsonResponse');
        ...
    

    you can also use tools like Postman to manually verify the API response and ensure it matches the expected structure.
    check the structure of the data you are trying to model it is probably a mismatch in it (the data structure not matching the expected format or being null when it shouldn’t be)

    let me know if it was helpful.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search