Flutter http get request json serialization - android

I would like to make a get requests and to convert results to a list of objects.
Actually i did that :
post_model.dart
#JsonSerializable()
class Post {
Post({
required this.userId,
required this.id,
required this.title,
required this.body,
});
factory Post.fromJson(Map<String, dynamic> json) => _$PostFromJson(json);
Map<String, dynamic> toJson() => _$PostToJson(this);
final int userId;
final int id;
final String title;
final String body;
}
http_service.dart :
class HttpService {
final String url = 'https://jsonplaceholder.typicode.com';
final String postsURL = '/posts';
final Map<String, String> headers = {
'Content-Type': 'application/json'
};
List<Post> parsePosts(String responseBody) {
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Post>((json) => Post.fromJson(json)).toList();
}
Future<List<Post>> fetchPosts() async {
final http.Response response = await http.get(Uri.https(url, postsURL));
if (response.statusCode == 200) {
return compute(parsePosts,response.body);
} else {
throw Exception("Failed to load posts ${response.statusCode}");
}
}
}
But i encouter all in red on the parsePosts method.
On the final parsed :
Missing variable type for 'parsed'.
Try adding an explicit type, or remove implicit-dynamic from your analysis options file.dart(implicit_dynamic_variable)
and on the return :
A value of type 'dynamic' can't be returned from the method 'parsePosts' because it has a return type of 'List<Post>'
I just don't understand what i'm doing wrong, because i have follow the flutter doc here :
https://flutter.dev/docs/cookbook/networking/background-parsing
Thanks for any help

Some time ago I did this code for that API:
import 'dart:async';
import 'package:wnetworking/wnetworking.dart';
class Post {
int? userId, id;
String? title, body;
Post.fromJson(Map<String, dynamic> data) {
userId = data['userId'];
id = data['id'];
title = data['title'];
body = data['body'];
}
}
class JsonPlaceHolder {
static const baseUrl = 'https://jsonplaceholder.typicode.com';
/* ---------------------------------------------------------------------------- */
static FutureOr<void> _doGet(String path, {void doThis(var response)?}) async {
await HttpReqService.getJson(baseUrl + path)
.then((response) => doThis == null ? print(response) : doThis(response))
.whenComplete(() => print('\nFetching done!'));
}
/* ---------------------------------------------------------------------------- */
static FutureOr<void> _doPost(String path, {required Object body, int okCode = 200}) async {
await HttpReqService.post<Map<String, dynamic>>(baseUrl + path, body: body, okCode: okCode)
.then((response) => print(response))
.whenComplete(() => print('\nPost sent successfully'));
}
/* ---------------------------------------------------------------------------- */
static FutureOr<void> fetchPosts({int? id, bool onlyComments = false, bool useObjList = false}) async {
var path = '/posts/${id ?? ''}';
if (id != null && onlyComments) path += '/comments';
useObjList
? await _doGet(path, doThis: (response) {
if (response != null) {
print((response as List).map<Post>((m) => Post.fromJson(m as Map<String, dynamic>)));
}
})
: await _doGet(path);
}
/* ---------------------------------------------------------------------------- */
static FutureOr<void> fetchComments([int? postId]) => _doGet('/comments${postId != null ? '?postId='+postId.toString() : ''}');
static FutureOr<void> fetchAlbums() => _doGet('/albums');
static FutureOr<void> fetchPhotos() => _doGet('/photos');
static FutureOr<void> fetchTodos() => _doGet('/todos');
static FutureOr<void> fetchUsers() => _doGet('/users');
}
void main(List<String> args) async {
// await JsonPlaceHolder.fetchComments(1);
await JsonPlaceHolder.fetchPosts(useObjList: true);
print('Finished!');
}
Result:
(Instance of 'Post', Instance of 'Post', Instance of 'Post', ..., Instance of 'Post', Instance of 'Post')
Fetching done!
Finished!
Note
wnetworking package is not ready to publish yet, it contains operations related to API, etc. You can replace HttpReqService.getJson and HttpReqService.post with your typical http.get and http.post respectively but keep in mind the return value and exceptions.
Use Uri.parse

Those errors are due to a dart version.
A fix has been made by another user on github : https://github.com/flutter/website/pull/5798
Following this PR, it's works

Related

2 Problems from Flutter Beginner Course from Angela, Clima project after refactoring code

1) From loading_screen.dart :
Error : Instance member 'getData' can't be accessed using static access.
Locator( ) is my location handling class.
import 'package:flutter/material.dart';
import 'package:clima/services/location_handler.dart';
import 'package:clima/services/networking.dart';
const myAPI = 'cant post api online but its just alphabets and numbers passed as a string';
class LoadingScreen extends StatefulWidget {
#override
_LoadingScreenState createState() => _LoadingScreenState();
}
class _LoadingScreenState extends State<LoadingScreen> {
late double latitood;
late double longitood;
void initState() {
//this method is called the moment we run our app.
super.initState();
getLocationData();
}
void getLocationData() async {
Locator loca = Locator();
await loca.getCurrentLocation();
latitood = loca.latitude;
longitood = loca.longitude;
NetworkHelper NetHelp = NetworkHelper(
//pasing url info into Network Helper class.
'https://api.openweathermap.org/data/2.5.weather?lat=$latitood&lon=$longitood&appid=$myAPI');
var weatherDataFinal = await NetworkHelper.getData();
}
#override
Widget build(BuildContext context) {
return Scaffold();
}
}
2) From networking.dart :
Error : The argument type 'String' can't be assigned to the parameter type 'Uri'.
import 'dart:convert'; /
import 'package:http/http.dart' as http;
class NetworkHelper {
NetworkHelper(this.url);
final String url;
Future getData() async {
http.Response response = await http.get(url);
//passing url as a single string to get method to get Response.
if (response.statusCode == 200) {
String data = response.body;
var decodedData = jsonDecode(data);
//decoding and putting data into decodedData variable of dynamic type.
return decodedData;
} else {
print(response.statusCode);
}
}
}
Did someone encounter these problems ? If you did and found a Solution then please help me !!!!
This await NetworkHelper.getData(); should be await NetHelp.getData(); because that is how you named your variable.
await http.get(url); should be await http.get(Uri.parse(url));

GetStorage always returns null in flutter

Code
print("Before : ${GetStorage().read("XXX")}");
GetStorage().write("XXX", 1);
print("After : ${GetStorage().read("XXX")}");
This is my Code. Every time I run the App, the Output is
Before : null
After : 1
Why is the storage data getting cleared everytime I restart the App? I thought this was an alternative to SharedPreference which works just fine. Have I missed something?
Before anything, initialize the package, normally I do this on main.dart
main() async {
await GetStorage.init();
}
Create an instance from GetStorage, I always put a name on the box, if not it will put "GetStorage" by default. It needs to have a name so it can retrieve your data.
GetStorage getStorage = GetStorage('myData');
After that you can write and retrieve data from it, I recommend you to "await" all reads and writes.
await getStorage.write('XXX', 1);
var a = await getStorage.read('XXX');
print(a); /// 1
I recommend you to put a name on the box according to what you are storing.
You should await for GetStorage.init().
void main() async {
await GetStorage.init();
print("Before : ${GetStorage().read("XXX")}");
GetStorage().write("XXX", 1);
print("After : ${GetStorage().read("XXX")}");
}
final _userBox = () => GetStorage('User');
class UserPref {
void call(){
_userBox.call()..initStorage;
}
dynamic setValueInt(String key, int value) {
return 0.val(key, getBox: _userBox).val = value;
}
String setValue(String key, String value) {
return ''.val(key, getBox: _userBox).val = value;
}
dynamic getValueInt(String key) {
return (-1).val(key,getBox: _userBox).val;
}
dynamic getValue(String key) {
return ''.val(key,getBox: _userBox).val;
}
void setUser(User user) {
''.val('uname', getBox: _userBox).val = user.uname ?? '';
(-1).val('gender', getBox: _userBox).val = user.gender ?? -1;
''.val('born', getBox: _userBox).val = user.born.toString();
true.val('enabled', getBox: _userBox).val = user.enabled ?? true;
}
User getUser() {
final String? uname = ''.val('uname',getBox: _userBox).val;
final int? gender = (-1).val('gender',getBox: _userBox).val;
final DateTime? born = ''.val('born',getBox: _userBox).val == '' ? null : DateTime.parse(''.val('born',getBox: _userBox).val);
final bool? enabled = true.val('enabled',getBox: _userBox).val;
return User(
uname: uname,
gender: gender,
born: born,
enabled: enabled,
);
}
}
///INIT:
#override
void initState() {
//The init function must be written separately from the read/write function due to being asynchronous.
UserPref().call();
}
//OR
Future<void> main() async {
//await GetStorage.init();
UserPref().call();
}
///USAGE:
class MyStatefulWidget extends StatefulWidget {
final Users prefUser = UserPref().getUser();
...
}
//OR
#override
Widget build(BuildContext context) {
final Users prefUser = UserPref().getUser();
return ...;
}

Flutter Snapshot.hasData is always returning true

i need to fetch data from server and sometimes the data can be empty response from logcat is data snapshot.data is returning instance of my model Instance of 'MyItems' and the response from server when data is not available is
{
"data": []
}
the problem is snapshot.hasData is always returning true for empty response i have tested snapshot.data == null still its true.
Model class
import 'dart:convert';
MyItems myItemsFromJson(String str) => MyItems.fromJson(json.decode(str));
String myItemsToJson(MyItems data) => json.encode(data.toJson());
class MyItems {
MyItems({
this.dataa,
});
List<Datumm> dataa;
factory MyItems.fromJson(Map<String, dynamic> json) => MyItems(
dataa: List<Datumm>.from(json["data"].map((x) => Datumm.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"data": List<dynamic>.from(dataa.map((x) => x.toJson())),
};
}
class Datumm {
Datumm({
this.userId,
this.Name,
this.MiddelName,
});
String userId;
String Name;
String MiddelName;
factory Datumm.fromJson(Map<String, dynamic> json) => Datumm(
userId: json["user_id"],
Name: json["Name"],
MiddelName: json["MiddleName"],
);
Map<String, dynamic> toJson() => {
"user_id": userId,
"Name": crbtCode,
"MiddelName": artistName,
};
}
My Future api call
Future<MyItems> getUdata(String aName) async {
var url =
'https://cvbgng.com/test/${aName}';
final response = await http.get(url).timeout(Duration(seconds: 15000));
if (response.statusCode == 200) {
return MyItems.fromJson(json.decode(response.body));
} else {
throw Exception('Faild to load');
}
}
check the condition as snapshot.data.dataa.isEmpty if it is true you have empty response.

Parsing nested JSON from cloud in dart but getting type error

I'm trying to to parse JSON from cloud, the data was received,
I tried so many solution here in stackOverflow but the haven't work to me, I'm just string to get familiar with flutter and dart.
but i got this error:
type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'List<Category>'
here it is my code:
JSON data I received:
{
"totalRowCount": 1,
"pageSize": 100,
"categories": [{
"CategoryName": "Beverages",
"CategoryID": 1
}]
}
Services.dart
import 'package:http/http.dart' as http;
import 'Category.dart';
class Services {
static const String url = 'http://example.com/category';
static Future<List<Category>> getCategories() async {
http.Response response = await http.get(url, headers: {"Accept": "application/json"});
if(response.statusCode == 200){
final category = categoryFromJson(response.body);
return category;
} else{
return List<Category>();
}
}
}
Category.dart
import 'dart:convert';
List<Category> categoryFromJson(String str) => List<Category>.from(json.decode(str));
class Category {
Category({
this.totalRowCount,
this.pageSize,
this.categories,
});
final int totalRowCount;
final int pageSize;
final List<CategoryElement> categories;
factory Category.fromJson(Map<String, dynamic> json){
return Category(
totalRowCount: json["totalRowCount"],
pageSize: json["pageSize"],
categories: List<CategoryElement>.from(json["categories"]),
);
}
Map<String, dynamic> toJson() => {
"totalRowCount": totalRowCount,
"pageSize": pageSize,
"categories": List<dynamic>.from(categories.map((x) => x.toJson())),
};
}
class CategoryElement {
CategoryElement({
this.categoryName,
this.categoryId,
});
final String categoryName;
final int categoryId;
factory CategoryElement.fromJson(Map<String, dynamic> json) => CategoryElement(
categoryName: json["CategoryName"],
categoryId: json["CategoryID"],
);
Map<String, dynamic> toJson() => {
"CategoryName": categoryName,
"CategoryID": categoryId,
};
}
any help
You need to call jsonDecode on response.body to convert the response to a Map.
import 'dart:convert';
final category = Category.fromJson(jsonDecode(response.body));
Remove the following line, it's causing the issue. Decode it right away using the factory instead of creating another function. That function is invalid because List.from accepts an iterable and you're supplying a Map. Also, the json response is not a List.
List<Category> categoryFromJson(String str) => List<Category>.from(json.decode(str));

Exception: _InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'int' in type cast

In my flutter application, I AM PREPARING data to be sent via a REST call. Below is my code.
Future<void> saveOrderItemList(List<OrderItem> orderItems) async {
int responsetag = 0;
try {
List jsonList = OrderItem.encondeToJson(orderItems);
await http.post(_navLinks.saveOrderItems(),
body: jsonList,
headers: {
"Accept": "application/json",
"content-type": "application/json"
}).then((http.Response response) {
final int statusCode = response.statusCode;
print("RESPONSE: " + response.body);
print("STATUS CODE: " + statusCode.toString());
if (statusCode < 200 || statusCode > 400 || response.body == null) {
throw new Exception("Error while fetching data");
} else {
responsetag = int.parse(response.body);
}
});
return responsetag;
} catch (error) {
throw (error);
}
}
Below code shows the OrderItem model class
part 'order_item.g.dart';
/// An annotation for the code generator to know that this class needs the
/// JSON serialization logic to be generated.
#JsonSerializable()
class OrderItem {
int idorderItem;
FreshProducts freshProducts;
Order order;
ProductSize productSize;
double orderItemExpectedPricePerKg;
double orderItemQuantity;
int dateCreated;
int lastUpdated;
OrderItem(
{this.idorderItem,
this.freshProducts,
this.order,
this.productSize,
this.orderItemExpectedPricePerKg,
this.orderItemQuantity,
this.dateCreated,
this.lastUpdated});
/// A necessary factory constructor for creating a new instance
/// from a map. Pass the map to the generated `_$OrderItemFromJson()` constructor.
/// The constructor is named after the source class, in this case User.
factory OrderItem.fromJson(Map<String, dynamic> json) =>
_$OrderItemFromJson(json);
/// `toJson` is the convention for a class to declare support for serialization
/// to JSON. The implementation simply calls the private, generated
/// helper method `_$OrderItemToJson`.
Map<String, dynamic> toJson() => _$OrderItemToJson(this);
static List encondeToJson(List<OrderItem> list) {
List jsonList = List();
list.map((item) => jsonList.add(item.toJson())).toList();
return jsonList;
}
}
Below code shows the JSOB Serialization generated for the model class
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'order_item.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
OrderItem _$OrderItemFromJson(Map<String, dynamic> json) {
return OrderItem(
idorderItem: json['idorderItem'] as int,
freshProducts: json['freshProducts'] == null
? null
: FreshProducts.fromJson(json['freshProducts'] as Map<String, dynamic>),
order: json['order'] == null
? null
: Order.fromJson(json['order'] as Map<String, dynamic>),
productSize: json['productSize'] == null
? null
: ProductSize.fromJson(json['productSize'] as Map<String, dynamic>),
orderItemExpectedPricePerKg:
(json['orderItemExpectedPricePerKg'] as num)?.toDouble(),
orderItemQuantity: (json['orderItemQuantity'] as num)?.toDouble(),
dateCreated: json['dateCreated'] as int,
lastUpdated: json['lastUpdated'] as int,
);
}
Map<String, dynamic> _$OrderItemToJson(OrderItem instance) => <String, dynamic>{
'idorderItem': instance.idorderItem,
'freshProducts': instance.freshProducts,
'order': instance.order,
'productSize': instance.productSize,
'orderItemExpectedPricePerKg': instance.orderItemExpectedPricePerKg,
'orderItemQuantity': instance.orderItemQuantity,
'dateCreated': instance.dateCreated,
'lastUpdated': instance.lastUpdated,
};
However when I run my saveOrderItemList function, I get the following error.
I/flutter (23028): type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'int' in type cast
Why is this happening?

Categories

Resources