I'm carrying out a basic fetch API request in the code below. The response I'm receiving gives the values for most of the properties except for two which come as null. This has me thinking if it is my code that's causing this issue to occur or something on the backend side which results into this anomaly. As shown below, the fiels that come as null in my VS Code terminal are product_description
and restaurant_id
. Although these come as null when displayed on the terminal, on Postman it is a different story as the response comes in full. The code and the responses are as follows:
Response on Postman:
{
"status": "success",
"data": [
{
"product_id": 8,
"restaurant_name": "Mocambo",
"restaurant_id": "6", //This is the field in question
"product_name": "Kaju Paneer",
"product_description": "Tasty yummy paneer gravy dish", //And So is this
"product_image": "/public/assets/product/lgml5L03-19-41.jpg",
"product_selling_price": "320"
}
]
}
Response received on Terminal after API Call:
{"status":"success","data":[{"product_id":8,"restaurant_name":"Mocambo","restaurant_id":"6","product_name":"Kaju Paneer","product_description":"Tasty yummy paneer gravy dish","product_image":"\/public\/assets\/product\/lgml5L03-19-41.jpg","product_selling_price":"320"}
When I try printing all the properties this is what I get(You can see above that I still receive data for restaurant_id
and product_description
)
I/flutter (10235): Provider product_selling_price 320
I/flutter (10235): Provider product_image /public/assets/product/lgml5L03-19-41.jpg
I/flutter (10235): Provider product_name Kaju Paneer
I/flutter (10235): Provider product_id 8
I/flutter (10235): Provider restaurantName Mocambo
I/flutter (10235): Provider Restaurant ID null //Restaurant ID here comes as null
I/flutter (10235): Provider Restaurant Description null //Restaurant Description comes as null
The codes for the Model Class, the class from which the API is called and the widget where it is used are below:
Model Class
import 'package:meta/meta.dart';
import 'dart:convert';
PopularDishes popularDishesFromJson(String str) =>
PopularDishes.fromJson(json.decode(str));
String popularDishesToJson(PopularDishes data) =>
json.encode(data.toJson());
class PopularDishes {
PopularDishes ({
required this.status,
required this.data,
});
String status;
List<Datum> data;
factory PopularDishes .fromJson(Map<String, dynamic> json) =>
PopularRestaurants(
status: json["status"],
data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"status": status,
"data": List<dynamic>.from(data.map((x) => x.toJson())),
};
}
class Datum {
Datum({
required this.productId,
required this.restaurantName,
required this.restaurantId,
required this.productName,
required this.productDescription,
required this.productImage,
required this.productSellingPrice,
});
int productId;
String restaurantName;
String restaurantId;
String productName;
String productDescription;
String productImage;
String productSellingPrice;
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
productId: json["product_id"],
restaurantName: json["restaurant_name"],
restaurantId: json["restaurant_id"],
productName: json["product_name"],
productDescription: json["product_description"],
productImage: json["product_image"],
productSellingPrice: json["product_selling_price"],
);
Map<String, dynamic> toJson() => {
"product_id": productId,
"restaurant_name": restaurantName,
"restaurant_id": restaurantId,
"product_name": productName,
"product_description": productDescription,
"product_image": productImage,
"product_selling_price": productSellingPrice,
};
}
The class from where the API is called
class PopularDishesProvider with ChangeNotifier {
Map<String, dynamic> _popularDishes = {};
String baseUrl = 'https://achievexsolutions.in/current_work/eatiano/';
Map<String, dynamic> get popularDishes {
return {..._popularDishes};
}
Future<void> fetchData() async {
final url = Uri.parse(baseUrl 'api/all_products');
final response = await http.get(url);
print(response.body);
PopularDishes popularDishes = popularDishesFromJson(response.body);
_popularDishes = popularDishes.toJson();
// print(_popularDishes);
}
}
The widget
class PopularDishes extends StatefulWidget {
PopularDishesState createState() => PopularDishesState();
}
class PopularDishesState extends State<PopularDishes> {
bool _isLoading = true;
@override
void didChangeDependencies() {
// TODO: implement didChangeDependencies
super.didChangeDependencies();
Provider.of<PopularDishesProvider>(context).fetchData().then((_) {
setState(() {
_isLoading = false;
});
});
}
@override
Widget build(BuildContext context) {
var width = MediaQuery.of(context).size.width;
var height = MediaQuery.of(context).size.height;
var textScale = MediaQuery.of(context).textScaleFactor * 1.1;
var subTitleScale = MediaQuery.of(context).textScaleFactor * 1.4;
final provider = Provider.of<PopularDishesProvider>(context).popularDishes;
print(
'Provider product_selling_price ${provider['data'][0]['product_selling_price']}');
print('Provider product_image ${provider['data'][0]['product_image']}');
print('Provider product_name ${provider['data'][0]['product_name']}');
print('Provider product_id ${provider['data'][0]['product_id']}');
print('Provider restaurantName ${provider['data'][0]['restaurant_name']}');
print('Provider Restaurant ID ${provider['data'][0]['restaurant_id']}'); //Returns null here
print(
'Provider Restaurant Description ${provider['data'][0]['product_description']}'); //Returns null here
}
}
Is there anything I can do to fix this or is this a backend issue?
CodePudding user response:
It may happen if some of your restaurant_id contains null value. If you are getting the response of data Try as follows:
provider['data'][0]['restaurant_id']==null?
print("isEmpty") :
print('Provider Restaurant ID ${provider['data'][0]['restaurant_id']}');
CodePudding user response:
Note, I could not check your Model class because you did not provide PopularRestaurants. Also, I may be mistaken but I don't think you should make async-await function calls inside provider. First call fetchData
in your StatefulWidget, then save the data in your provider. I also think you're using didChangeDependencies wrong and what you want is initstate.
This works for me:
Model Class generated from https://javiercbk.github.io/json_to_dart/
class PopularDishesModel {
String? status;
List<Data>? data;
PopularDishesModel({this.status, this.data});
PopularDishesModel.fromJson(Map<String, dynamic> json) {
status = json['status'];
if (json['data'] != null) {
data = <Data>[];
json['data'].forEach((v) {
data!.add(Data.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['status'] = status;
if (this.data != null) {
data['data'] = this.data!.map((v) => v.toJson()).toList();
}
return data;
}
}
class Data {
int? productId;
String? restaurantName;
String? restaurantId;
String? productName;
String? productDescription;
String? productImage;
String? productSellingPrice;
Data(
{this.productId,
this.restaurantName,
this.restaurantId,
this.productName,
this.productDescription,
this.productImage,
this.productSellingPrice});
Data.fromJson(Map<String, dynamic> json) {
productId = json['product_id'];
restaurantName = json['restaurant_name'];
restaurantId = json['restaurant_id'];
productName = json['product_name'];
productDescription = json['product_description'];
productImage = json['product_image'];
productSellingPrice = json['product_selling_price'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['product_id'] = productId;
data['restaurant_name'] = restaurantName;
data['restaurant_id'] = restaurantId;
data['product_name'] = productName;
data['product_description'] = productDescription;
data['product_image'] = productImage;
data['product_selling_price'] = productSellingPrice;
return data;
}
}
This is my stateful widget
class PopularDishes extends StatefulWidget {
PopularDishesState createState() => PopularDishesState();
}
class PopularDishesState extends State<PopularDishes> {
String baseUrl = 'https://achievexsolutions.in/current_work/eatiano/';
//Initialize PopularDishesModel
PopularDishesModel savedModel = PopularDishesModel();
//Make sure all json is downloaded
bool _isLoading = true;
//Remove this function from provider and put in your widget
Future<PopularDishesModel> fetchData() async {
final url = Uri.parse(baseUrl 'api/all_products');
final response = await http.get(url);
//print(response.body);
PopularDishesModel popularDishes = PopularDishesModel.fromJson(json.decode(response.body));
return popularDishes;
}
//This is an async function f
void GetRestaurantData() async
{
PopularDishesModel result = await fetchData();
setState(() {
savedModel = result;
_isLoading = false;
});
}
@override
void initState() {
super.initState();
GetRestaurantData();
}
@override
Widget build(BuildContext context) {
var width = MediaQuery.of(context).size.width;
var height = MediaQuery.of(context).size.height;
var textScale = MediaQuery.of(context).textScaleFactor * 1.1;
var subTitleScale = MediaQuery.of(context).textScaleFactor * 1.4;
//Add code to save to provider
if(_isLoading == false) {
print(savedModel.data![0].productId);
print(savedModel.data![0].restaurantName);
print(savedModel.data![0].restaurantId);
print(savedModel.data![0].productName);
print(savedModel.data![0].productDescription);
print(savedModel.data![0].productImage);
print(savedModel.data![0].productSellingPrice);
/*Result
8
Mocambo
6
Kaju Paneer
Tasty yummy paneer gravy dish
/public/assets/product/lgml5L03-19-41.jpg
320*/
}
//Add logic to save to provider
return Container();
}
}