Home > Blockchain >  How to get a list of products from API
How to get a list of products from API

Time:02-28

I am trying to call an API and get a list of products in my example. Getting a single product and convert it into a dart object works already. However when I try to get a list of products I can't manage to do that.

I read the official documentation of Flutter but they only show how to retrieve 1 item from the API instead of a list of items...

I checked a lot of tutorials but it does not seem to work that well either. I never thought this would be that hard.

Structure

I got a product_service that is responsible for the API call and I got a product model. Which contains the properties (name for example).

How does the code look like?

product_service.dart

// Endpoint : Get product by id
  Future<Product> getProductById(int productId) async {
    String basicAuth =
        'Basic '   base64Encode(utf8.encode('$username:$password'));
    print(basicAuth);

    var response = await http.get(
        Uri.parse(
            'https://website/wp-json/wc/v3/products/${productId}'),
        headers: <String, String>{'authorization': basicAuth});
    if (response.statusCode == 200) {
      //return response.body;
      return Product.fromJson(jsonDecode(response.body));
    } else {
      throw Exception('Failed to load product');
    }
// Endpoint : Get all products
  Future<List<Product>> getAllProducts() async {
    String basicAuth =
        'Basic '   base64Encode(utf8.encode('$username:$password'));
    print(basicAuth);

    Product? product;

    var r = await http.get(
        Uri.parse(
            'https://website/wp-json/wc/v3/products?post_per_page=1'),
        headers: <String, String>{'authorization': basicAuth});
    if (r.statusCode == 200) {
      print(r.body);
      product = Product().productsFromJson(jsonDecode(r.body));
    }
    return [];
  }

product model

class Product {
  // Properties
  String name;
  String description;
  String price;
  List<dynamic> images;
  int stockQuantity;
  List<Category> categories;
  // Constructor
  Product(
      {required this.name,
      required this.description,
      required this.price,
      required this.stockQuantity,
      required this.images,
      required this.categories});

  // Make a product object from json
  factory Product.fromJson(Map<String, dynamic> json) {
    List<Category> categorieList = [];
    for (var cat in json['categories']) {
      Category category = Category(name: cat['name'], slug: cat['slug']);
      categorieList.add(category);
    }

    return Product(
        name: json['name'],
        description: json['description'],
        price: json['price'],
        stockQuantity: json['stock_quantity'],
        images: json['images'],
        categories: categorieList);
  }

// Make list of products from json 
List<Product> productsFromJson(Map<String, dynamic> json) {
    List<Product> products = [];
    json.forEach((key, value) {
      Product p = Product.fromJson(value);
      products.add(p);
    });
    return products;
}

What goes wrong?

I kept some code out to make the code more readable for everyone. I tried to add an extra function in my product model but I cannot call it in my product_service.dart. This is because the parameters like name and price is required. I can make it all nullable and do the following:

String? name;

But I am not sure if this is a best practice to do. What is the best practice for this problem?

I also have a question about Future. Why should you use future when someone can use Async and Await without Future and then return a List?

Thank you all!

CodePudding user response:

When you edit the model class like this the problem will be solved,

class Product {
  // Properties
  String name;
  String description;
  String price;
  List<dynamic> images;
  int stockQuantity;
  List<Category> categories;
  // Constructor
  Product(
      {required this.name,
      required this.description,
      required this.price,
      required this.stockQuantity,
      required this.images,
      required this.categories});

       factory Product.fromJson(Map<String, dynamic> json) =>
      Product(
        name:json["name"],
        description:json["description"],
        price:json["price"],
        stockQuantity:json["stockQuantity"],
        images:json["images"],

        categories: List<Category>.from(
                json["categories"].map((x) => Category.fromJson(x))),
      );
}

Category model should be like this:

    class Category {
  // Properties
  String categoryName;
  String categoryDescription;
  String categoryImages;
  // Constructor
  Category({
    required this.categoryName,
    required this.categoryDescription,
    required this.categoryImages,
  });
  factory Category.fromJson(Map<String, dynamic> json) => Category(
        categoryName: json["categoryName"],
        categoryDescription: json["categoryDescription"],
        categoryImages: json["categoryImages"],
      );
}

CodePudding user response:

 Future<List<Product>> getAllProducts() async {
String basicAuth =
    'Basic '   base64Encode(utf8.encode('$username:$password'));
print(basicAuth);

//Removed the product type 

var r = await http.get(
    Uri.parse(
        'https://website/wp-json/wc/v3/products?post_per_page=1'),
    headers: <String, String>{'authorization': basicAuth});

//Made your code a little more readable here
if (r.statusCode == 200) {
  String data = response.body;
  var decodedData  = json.decode(data);
  return decodedData;

}else {
return r.statusCode;
}

//Now to get a list of products you need a new function 

 Future<List<Product>> getProductsList () async{
 //Here we will call the data from the API into a variable 
  var products = await getAllProducts();
  List<Product> productList = [];
   
  for( p in products){
   Product _product = Product(
    name : p['name'],
    description :p['description'],

 //I trust you get the gist here, do this for all map values

   );

 //Here we are going to add each of the items to the list above

   productList.add(Product.fromjson(p));
  
  }
   return productList;
 }

You will need to make use of a FutureBuilder of type {Product} to display your items

  • Related