I'm trying to fetch data from an api by passing bearer token but it is throwing this exception. Here's my code below :
This is my afterLoginResponse.dart class -
class AfterLoginResponse {
LoginData? data;
bool? operator;
bool? success;
AfterLoginResponse({
required this.operator,
required this.success,
required this.data,
});
AfterLoginResponse.fromJson(Map<String, dynamic> json) {
operator = json['operator'];
success = json['success'];
data = LoginData.fromJson(json["data"]);
}
Map<String, dynamic> toJson() => {
"operator": operator,
"success": success,
"data": data!.toJson(),
};
}
Below is my loginData.dart class ->
class LoginData {
String? name;
String? ext;
String? dName;
String? password;
LoginData({
required this.name,
required this.ext,
required this.dName,
required this.password,
});
factory LoginData.fromJson(Map<String, dynamic> json) {
return LoginData(
name: json['name'],
ext: json['ext'],
dName: json['d_Name'],
password : json['password'],
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['name'] = name;
data['ext'] = ext;
data['d_Name'] = dName;
data['password'] = password;
return data;
}
}
This is my apiService.dart class -
class ApiService{
String? token;
var response1;
var response2;
Future<LoginResponseData> loginApiCall(Map<String, dynamic> param) async{
var url = Uri.parse(ApiUrls.login_url);
response1 = await http.post(url, body: param);
final data = jsonDecode(response1.body);
token = LoginResponseData.fromJson(json.decode(response1.body)).token;
return LoginResponseData(user: data['user'], token:
data['token'],error:data['error']);
}
Future<AfterLoginResponse> postLoginApiCall() async{
var afterLoginUrl = Uri.parse(ApiUrls.postLogin_url);
response2 = await http.get(afterLoginUrl , headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer
${LoginResponseData.fromJson(json.decode(response1.body)).token}'
});
if(response2.statusCode == 200){
var data = jsonDecode(response2.body);
return AfterLoginResponse.fromJson(data);
}else{
throw Exception('Failed to load data');
}
}
}
Here is my UI -
class HomePage extends StatefulWidget {
String email, password;
HomePage({Key? key, required this.email, required this.password})
: super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
late Future<AfterLoginResponse> afterLoginResponse;
final apiService = ApiService();
callPostLoginApi(){
return FutureBuilder<AfterLoginResponse>(
future: afterLoginResponse,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!);
print(snapshot.data);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
// By default, show a loading spinner.
return const CircularProgressIndicator();
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home page'),
centerTitle: true,
),
body: Center(
child: Column(
children: [
ElevatedButton(
onPressed: callPostLoginApi,
child: const Text('Click me'))
],
),
)
);
}
The above code is throwing following exception -
Unhandled Exception: NoSuchMethodError: The getter 'body' was called on null.
Receiver: null
E/flutter (28599): Tried calling: body
E/flutter (28599): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:38:5)
.
.
.
in the postLoginApiCall you are calling body with response1 variable which is at that very time null that is causing the issue change that to response2 like this:
Future<AfterLoginResponse> postLoginApiCall() async{
var afterLoginUrl = Uri.parse(ApiUrls.postLogin_url);
response2 = await http.get(afterLoginUrl , headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer
${LoginResponseData.fromJson(json.decode(response2.body)).token}'
});
if(response2.statusCode == 200){
var data = jsonDecode(response2.body);
return AfterLoginResponse.fromJson(data);
}else{
throw Exception('Failed to load data');
}
}
}
You should call the postLoginApiCall after getting response from the loginApiCall
Future<LoginResponseData> loginApiCall(Map<String, dynamic> param) async{
...
}
Future<AfterLoginResponse> postLoginApiCall() async{
...
}
loginApiCall().then((value) => postLoginApiCall()); // like this
Related
I have a flutter project which is returning a list of data from an api in Json, I want to show the data as a list for a specific key which is name but currently I keep reciving:
type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>'
Here is the future builder
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
late Future<Workouts_Model> futureWorkouts;
#override
void initState() {
super.initState();
futureWorkouts = APIService.fetchUserWorkout();
}
...................................
FutureBuilder<Workouts_Model>(
future: futureWorkouts,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!.name ?? 'noname');
} else if (snapshot.hasError) ;
print(snapshot.error);
{
return Text('${snapshot.error}');
}
return const CircularProgressIndicator();
},
),
Here is the api_caller:
static Future<Workouts_Model> fetchUserWorkout() async {
var url = Uri.parse(Config.apiURL + Config.userWorkoutsAPI);
final response = await http.get(
url,
headers: {
HttpHeaders.authorizationHeader:
'Token XXXXXXXXXXXXXXX',
},
);
final responseJson = jsonDecode(response.body);
print(responseJson);
if (response.statusCode == 200) {
return Workouts_Model.fromJson(jsonDecode(response.body));
} else {
throw Exception('Failed to load User');
}
}
Here is the model:
import 'dart:convert';
List<Workouts_Model> workoutsModelFromJson(String str) =>
List<Workouts_Model>.from(
json.decode(str).map((x) => Workouts_Model.fromJson(x)));
String workoutsModelToJson(List<Workouts_Model> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Workouts_Model {
Workouts_Model({
required this.id,
required this.user,
required this.name,
});
int id;
String user;
String name;
factory Workouts_Model.fromJson(Map<String, dynamic> json) => Workouts_Model(
id: json["id"],
user: json["user"],
name: json["name"],
);
Map<String, dynamic> toJson() => {
"id": id,
"user": user,
"name": name,
};
}
How to show the list of name in the model so that I can see it when the application is running.
since I see that the API will return multiple elements, then it's a List right?
in this line:
return Workouts_Model.fromJson(jsonDecode(response.body));
you're trying to assign a List to Map<String, dynamic>, which is wrong, you need to make a List<Workouts_Model> of the List of data in the API, so replace your method like this:
static Future<List<Workouts_Model>> fetchUserWorkout() async {
var url = Uri.parse(Config.apiURL + Config.userWorkoutsAPI);
final response = await http.get(
url,
headers: {
HttpHeaders.authorizationHeader:
'Token XXXXXXXXXXXXXXX',
},
);
final responseJson = jsonDecode();
print(responseJson);
if (response.statusCode == 200) {
return workoutsModelFromJson(response.body);
} else {
throw Exception('Failed to load User');
}
}
then change this:
late Future<Workouts_Model> futureWorkouts;
to this:
late Future<List<Workouts_Model>> futureWorkouts;
then in your FutureBuilder:
FutureBuilder<List<Workouts_Model>>(
future: futureWorkouts,
builder: (BuildContext context, AsyncSnapshot<List<Workouts_Model>> snapshot) {
if (snapshot.hasData) {
return Column(
children: List.generate(snapshot.data!.length, (index) => Text(snapshot.data![index].name ?? 'noname')));
} else if (snapshot.hasError) ;
print(snapshot.error);
{
return Text('${snapshot.error}');
}
return const CircularProgressIndicator();
},
),
I am trying to show a list of Json name that is obtained from an API but when I try to display it I receive type List error as result of snapshot.error. I am not sure exactly how and which line is resulting in this error.
Here is the screen dart:
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
late Future<List<Workouts_Model>> futureWorkouts;
#override
void initState() {
super.initState();
futureWorkouts = APIService.fetchUserWorkout();
}
....................................
FutureBuilder<List<Workouts_Model>>(
future: futureWorkouts,
builder: (BuildContext context,
AsyncSnapshot<List<Workouts_Model>> snapshot) {
if (snapshot.hasData) {
return Column(
children: List.generate(snapshot.data!.length,
(index) => Text(snapshot.data![index].name)));
} else if (snapshot.hasError) ;
print(snapshot.error);
// throw snapshot.error!;
// //
{
return Text('${snapshot.error}'); <———error here
}
return const CircularProgressIndicator();
},
),
Here is the api called:
static Future<List<Workouts_Model>> fetchUserWorkout() async {
final response = await http.get(Uri.parse(...),
headers: {...},);
final responseJson = jsonDecode(response.body);
if (response.statusCode == 200) {
return workoutsModelFromJson(jsonDecode(response.body));
} else {
throw Exception('Failed to load User');
}
}
If I could get help on knowing why and how to solve it.
Here is the model:
List<Workouts_Model> workoutsModelFromJson(String str) =>
List<Workouts_Model>.from(
json.decode(str).map((x) => Workouts_Model.fromJson(x)));
String workoutsModelToJson(List<Workouts_Model> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Workouts_Model {
Workouts_Model({
required this.id,
required this.user,
required this.active,
required this.name,
required this.slug,
});
int id;
String user;
bool active;
String name;
String slug;
factory Workouts_Model.fromJson(Map<String, dynamic> json) => Workouts_Model(
id: json["id"],
user: json["user"],
active: json["active"],
name: json["name"],
slug: json["slug"],
);
Map<String, dynamic> toJson() => {
"id": id,
"user": user,
"active": active,
"name": name,
"slug": slug,
};
}
This is the result of final responseJson = jsonDecode(response.body); print(responseJson);
[{id: 4, user: Username, active: false, name: T-shirt1, slug: Upper1}, {id: 5, user: Username, active: false, name: T-shirt2, slug: Lower1}]
if you look closely you've already decoded your response.body which being past.
final responseJson = jsonDecode(response.body); // Decoded already
if (response.statusCode == 200) {
return workoutsModelFromJson(jsonDecode(response.body)); //// Decoded data is pasted to workoutsModelFromJson.
} else {
throw Exception('Failed to load User');
}
So your model "workoutsModelFromJson" should be
List<Workouts_Model> workoutsModelFromJson(dynamic decodedResponse) =>
List<Workouts_Model>.from(
decodedResponse.map((x) => Workouts_Model.fromJson(x)));
hi am new to flutter and i need to get data from a map using API I m struggling at the moment and don't know what to do I always keep getting a error Error '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Iterable'
this is the class code
// To parse this JSON data, do
//
// final aziz = azizFromJson(jsonString);
import 'dart:convert';
Demandes azizFromJson(String str) => Demandes.fromJson(json.decode(str));
String azizToJson(Demandes data) => json.encode(data.toJson());
class Demandes {
Demandes({
required this.srMboSet,
});
SrMboSet srMboSet;
factory Demandes.fromJson(Map<String, dynamic> json) => Demandes(
srMboSet: SrMboSet.fromJson(json["SRMboSet"]),
);
Map<String, dynamic> toJson() => {
"SRMboSet": srMboSet.toJson(),
};
}
class SrMboSet {
SrMboSet({
required this.rsStart,
required this.rsCount,
required this.sr,
});
int rsStart;
int rsCount;
List<Sr> sr;
factory SrMboSet.fromJson(Map<String, dynamic> json) => SrMboSet(
rsStart: json["rsStart"],
rsCount: json["rsCount"],
sr: List<Sr>.from(json["SR"].map((x) => Sr.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"rsStart": rsStart,
"rsCount": rsCount,
"SR": List<dynamic>.from(sr.map((x) => x.toJson())),
};
}
class Sr {
Sr({
required this.rowstamp,
required this.attributes,
});
String rowstamp;
Attributes attributes;
factory Sr.fromJson(Map<String, dynamic> json) => Sr(
rowstamp: json["rowstamp"],
attributes: Attributes.fromJson(json["Attributes"]),
);
Map<String, dynamic> toJson() => {
"rowstamp": rowstamp,
"Attributes": attributes.toJson(),
};
}
class Attributes {
Attributes({
required this.ticketid,
required this.attributesClass,
required this.description,
required this.status,
required this.statusdate,
required this.reportedby,
});
Class ticketid;
Class attributesClass;
Class description;
Class status;
Class statusdate;
Class reportedby;
factory Attributes.fromJson(Map<String, dynamic> json) => Attributes(
ticketid: Class.fromJson(json["TICKETID"]),
attributesClass: Class.fromJson(json["CLASS"]),
description: Class.fromJson(json["DESCRIPTION"]),
status: Class.fromJson(json["STATUS"]),
statusdate: Class.fromJson(json["STATUSDATE"]),
reportedby: Class.fromJson(json["REPORTEDBY"]),
);
Map<String, dynamic> toJson() => {
"TICKETID": ticketid.toJson(),
"CLASS": attributesClass.toJson(),
"DESCRIPTION": description.toJson(),
"STATUS": status.toJson(),
"STATUSDATE": statusdate.toJson(),
"REPORTEDBY": reportedby.toJson(),
};
}
class Class {
Class({
required this.content,
});
String content;
factory Class.fromJson(Map<String, dynamic> json) => Class(
content: json["content"],
);
Map<String, dynamic> toJson() => {
"content": content,
};
}
and this is my main code I always get a error if anyone can help please
// ignore_for_file: use_key_in_widget_constructors, avoid_print, avoid_unnecessary_containers, curly_braces_in_flow_control_structures, prefer_const_constructors, non_constant_identifier_names, unnecessary_new, avoid_function_literals_in_foreach_calls
import 'dart:convert';
import './demandes.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: DataFromAPI(),
);
}
}
class DataFromAPI extends StatefulWidget {
#override
_DataFromAPIState createState() => _DataFromAPIState();
}
class _DataFromAPIState extends State<DataFromAPI> {
List<Attributes> MyAllData = [];
#override
void initState() {
loadData();
}
loadData() async {
var response = await http.get(Uri.parse(
'http://192.168.1.30:9080/maxrest/rest/mbo/sr/?_lid=&_lpwd=&_format=json'));
if (response.statusCode == 200) {
String responseBody = response.body;
Map<String, dynamic> jsonBody = json.decode(responseBody);
for (var data in jsonBody) {
MyAllData.add(Attributes(
ticketid: data["ticketid"],
attributesClass: data["attributesClass"],
description: data["description"],
status: data["status"],
statusdate: data["statusdate"],
reportedby: data["reportedby"]));
}
setState(() {
MyAllData.forEach((somedata) => print("Name: ${somedata.ticketid}"));
});
} else {
print("theres something wrong...");
}
}
Widget build(BuildContext context) {
return MaterialApp(
home: new Scaffold(
appBar: AppBar(
title: Text('Liste des SR'),
),
body: MyAllData.length == 0
? new Center(
child: new CircularProgressIndicator(),
)
: showMyUI(),
),
);
}
Widget showMyUI() {
return new ListView.builder(
itemCount: MyAllData.length,
itemBuilder: ((_, index) {
return new Container(
child: new Card(
child: new Container(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Text(
'Ticket ID : ${MyAllData[index].ticketid}',
),
],
),
),
),
);
}));
}
}
So from your model class, what I see is that you have Attributes inside of Sr, but after your JSON decode, you went ahead to just add data to the attributes list, so that's where your error is coming from, you have not fully deserialised the data here's how you can do it and it would work
loadData() async {
var response = await http.get(Uri.parse(
'http://192.168.1.30:9080/maxrest/rest/mbo/sr/?_lid=&_lpwd=&_format=json'));
if (response.statusCode == 200) {
final jsonBody = json.decode(response.body);
Demandes data = Demandes.fromJson(jsonBody);
final srAttributes = data.srMboSet.sr;
// SR is your list attributes is just an object, So what you do is this
for (int attribute = 0; attribute < srAttributes.length; attribute++) {
MyAllData.add(srAttributes[attribute].attributes);
}
setState(() {
MyAllData.forEach((somedata) => print("Name: ${somedata.ticketid}"));
});
} else {
print("theres something wrong...");
}
}
I'm trying to load data from a mock recipes.json file in flutter and I have a structure like this
lib
|__mock_data
|__recipes.json
|__src
|__models
|__components
|__screens
|__app.dart
|__main.dart
Now I have created a model which looks like this:
class RecipeModel {
RecipeModel({
required this.id,
required this.name,
required this.videoLink,
required this.author,
required this.category,
required this.time,
});
String id;
String name;
String videoLink;
String author;
String category;
String time;
factory RecipeModel.fromJson(Map<String, dynamic> json) => RecipeModel(
id: json["id"] == null ? null : json["id"],
name: json["name"] == null ? null : json["name"],
videoLink:
json["audioAssetPath"] == null ? null : json["audioAssetPath"],
author: json["isRemoteUrl"] == null ? null : json["isRemoteUrl"],
category: json["iconUrl"] == null ? null : json["iconUrl"],
time: json["vol"] == null ? null : json["vol"].toDouble(),
);
}
In the page where I want to show the data I'm doing this:
Future<List<RecipeModel>> fetchRecipes() async {
String url =
"https://raw.githubusercontent.com/boriszv/json/master/random_example.json";
var response = await http.get(url); ----------->The argument type 'String' can't be assigned to the parameter type 'Uri'
print(response);
var recipes = <RecipeModel>[];
var recipesJson = json.decode(response.body);
for (var index in recipesJson) {
recipes.add(RecipeModel.fromJson(index));
}
throw '';
}
#override
void initState() {
super.initState();
fetchRecipes();
}
I get a error when assigning the URL and also how to load the current recipe.json data?
N.B: Are the models written right?Because there might be a shift from json to protobuf
To load a local file, you can put the file in the assets folder.
Future<List<RecipeModel>> loadLocalRecipe() async {
try {
String response = await rootBundle.loadString('assets/recipe.json');
List<dynamic> result = json.decode(response);
return result.map((n) => RecipeModel.fromJson(n)).toList();
} catch (e) {
throw Padding(
padding: EdgeInsets.only(top: 50),
child: Center(
child: Text('Convert Error'),
),
);
}
}
pubspec.yaml
flutter:
assets:
- assets/receipe.json
To get server data, you can use this.
Future<List<RecipeModel>> getRecipe() async {
try {
final http.Response response = await http.get("https://example.com",
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
);
// print(response.body);
List<dynamic> result = json.decode(response.body) as List;
return result.map((n) => RecipeModel.fromJson(n)).toList();
} catch (e) {
throw Padding(
padding: EdgeInsets.only(top: 50),
child: Center(
child: Text('Connection Error'),
),
);
}
}
I'm trying to get data from API using Rest Service..
But I got an error saying that the getter was called on null, after doing some research, I found something, like the UI which the data I want to display was executed first than the getData function, it makes the system read the variable as null and the error occurs. Can anybody help me with this case..
Here this is a bit of my codes,
class PickUp extends StatefulWidget {
var created_name, wmsorders_id, id;
PickUp(
{Key key,
#required this.created_name,
#required this.wmsorders_id,
#required this.id})
: super(key: key);
#override
_PickUpState createState() => _PickUpState();
}
class _PickUpState extends State<PickUp> {
DetailModel detailModel;
String sender = "";
Future<String> getDetail() async {
print("id : " + widget.id);
var data = "id=" + widget.id + "";
var response_detail = await RestService()
.restRequestServiceGet(SystemParam.URL_DETAIL_UPCOMING, data);
print("response_detail : " + response_detail.body.toString());
setState(() {
detailModel = DetailModel.fromJson(jsonDecode(response_detail.body));
});
return "Success!";
}
#override
void initState() {
getDetail();
}
Widget build(BuildContext context) {
// NULL CHECKING
if (detailModel != null) {
print("sender =" +detailModel.the0.picName);
} else {
print("sender = null");
}
// I want to get picName from detail Model and using it in UI, but I got Error here
sender = detailModel.the0.picName';
print("sender = " +'$sender');
}
Here is the detailModel
// To parse this JSON data, do
//
// final detailModel = detailModelFromJson(jsonString);
import 'dart:convert';
DetailModel detailModelFromJson(String str) => DetailModel.fromJson(json.decode(str));
String detailModelToJson(DetailModel data) => json.encode(data.toJson());
class DetailModel {
The0 the0;
The0 the1;
Records records;
DetailModel({
this.the0,
this.the1,
this.records,
});
factory DetailModel.fromJson(Map<String, dynamic> json) => DetailModel(
the0: The0.fromJson(json["0"]),
the1: The0.fromJson(json["1"]),
records: Records.fromJson(json["records"]),
);
Map<String, dynamic> toJson() => {
"0": the0.toJson(),
"1": the1.toJson(),
"records": records.toJson(),
};
}
class Records {
int status;
String message;
Records({
this.status,
this.message,
});
factory Records.fromJson(Map<String, dynamic> json) => Records(
status: json["status"],
message: json["message"],
);
Map<String, dynamic> toJson() => {
"status": status,
"message": message,
};
}
class The0 {
String id;
String sku;
int sak;
String qty;
String shipstatId;
String picName;
String picTelp;
String orderMultipleId;
String orderdetId;
String coordinatorId;
The0({
this.id,
this.sku,
this.sak,
this.qty,
this.shipstatId,
this.picName,
this.picTelp,
this.orderMultipleId,
this.orderdetId,
this.coordinatorId,
});
factory The0.fromJson(Map<String, dynamic> json) => The0(
id: json["id"],
sku: json["sku"],
sak: json["sak"],
qty: json["qty"],
shipstatId: json["shipstat_id"],
picName: json["pic_name"],
picTelp: json["pic_telp"],
orderMultipleId: json["order_multiple_id"],
orderdetId: json["orderdet_id"],
coordinatorId: json["coordinator_id"],
);
Map<String, dynamic> toJson() => {
"id": id,
"sku": sku,
"sak": sak,
"qty": qty,
"shipstat_id": shipstatId,
"pic_name": picName,
"pic_telp": picTelp,
"order_multiple_id": orderMultipleId,
"orderdet_id": orderdetId,
"coordinator_id": coordinatorId,
};
}
And here is the Error,
You need to use FutureBuilder in build method and wait until response.
Remove setstate and Modify the code as below.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'Test',
style: TextStyle(
color: Colors.white,
),
),
),
body: FutureBuilder<DetailModel>(
future: getDetail(),
builder: (context, snapshot) {
if (snapshot.hasData) {
print("Here you can get data "+snapshot.data.toString());
} else {
print("Waiting mode");
return Container(
color: Colors.blue,
);
}
},
),
);
}
}