After login I successfully got response from my api also can print the Data in my second screen by doing this Text("Status: ${widget.rresponse.status}"), .
But I want to print in snackbar.
What will be the the syntax to print json response data in my SnackBar?
Here is my Json response
{
"Status": "1",
"Message": "You are Logged in successfully",
"UserData": {
"Name": "qwerty#gmail.com",
"EncUserId": "GO9gj3aSUKCpxE3AMSbh/A=="
}
}
My Api got call when user press the login button
Future<void> login() async{
var jsonResponse;
if (passwordontroller.text.isNotEmpty && emailController.text.isNotEmpty) {
var response = await http.post(Uri.parse("http://ututututtutu"),
body: ({
'LoginId': emailController.text,
'Password': passwordontroller.text
}));
if (response.statusCode == 200) {
print("Correct");
print(response.body);
jsonResponse = json.decode(response.body.toString());
print(jsonResponse);
// ===========Successfully can print in my second screen ==================
// Navigator.push(context, MaterialPageRoute(builder: (context)=>AfterLoginResPage(rresponse: ApiResponse.fromJson(jsonResponse))));
//===========Trying to print in my snackBar========================
jsonResponse = jsonDecode(response.body.toString());//==
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content:Text("Message: ${jsonResponse['encUserId']}"))) ;
}
else {
print("Wronggooooooooooooooooooooooooooo");
print(response.body);
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("Invalid credentials")));
}
} else {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("Blank field is not allowed")));
}
}
And Here is my Model class
class ApiResponse {
ApiResponse({
required this.status,
required this.message,
required this.userData,
});
String status;
String message;
UserData? userData;
factory ApiResponse.fromJson(Map<String, dynamic> json) => ApiResponse(
status: json["Status"],
message: json["Message"],
userData: json["UserData"] == null? null:UserData.fromJson(json["UserData"] as Map<String, dynamic>),
);
}
class UserData {
UserData({
required this.name,
required this.encUserId,
});
String name;
String encUserId;
factory UserData.fromJson(Map<String, dynamic> json) => UserData(
name: json["Name"],
encUserId: json["EncUserId"],
);
Case sensitive. "EncUserId" != "encUserId"
Related
I'm trying to built an app for my college degree with flutter that has a login screen where you insert the username and password and pass to the main screen. I use retrofit for the REST API. When I press the login button with the credentials I get the error: Exception: DioError [DioErrorType.other]: type 'String' is not a subtype of type 'Map<String, dynamic>?' in type cast.
I'm very new in Flutter can you help me? Here is my code:
Api_Service
#RestApi(baseUrl: '...')
abstract class ApiService {
factory ApiService(Dio dio, {required String baseUrl}) {
dio.options = BaseOptions(
receiveTimeout: 3000,
connectTimeout: 3000,
contentType: 'application/json',
headers: <String, String>{
'Authorization': 'Basic Y29hY2g6Y29hY2g=',
'Accept': 'application/json',
},
followRedirects: false,
validateStatus: (status) {
return status! < 400;
});
return _ApiService(dio, baseUrl: baseUrl);
}
//Login Service
#POST('...')
#FormUrlEncoded()
Future<LoginResponse> login(#Body() Map<String, dynamic> body);
Api_Response
#JsonSerializable()
class LoginResponse {
//show login response data
#JsonKey(name: 'Status')
final int statusCode;
#JsonKey(name: 'Message')
final String message;
#JsonKey(name: 'Content')
final UserEntity userEntity;
LoginResponse(this.statusCode, this.message, this.userEntity);
factory LoginResponse.fromJson(Map<String, dynamic> json) =>
_$LoginResponseFromJson(json);
Map<String, dynamic> toJson() => _$LoginResponseToJson(this);
}
User_entity
import 'package:json_annotation/json_annotation.dart';
part 'user_entity.g.dart';
//done this file
#JsonSerializable()
class UserEntity {
#JsonKey(name: 'id')
final String id;
#JsonKey(name: 'username')
final String username;
#JsonKey(name: 'role')
final String role;
UserEntity(this.id, this.username, this.role);
factory UserEntity.fromJson(Map<String, dynamic> json) =>
_$UserEntityFromJson(json);
Map<String, dynamic> toJson() => _$UserEntityToJson(this);
}
User
class User {
String? id;
String? username;
String? role;
String? token;
String? renewalToken;
User({this.id, this.username, this.role, this.token, this.renewalToken});
factory User.fromJson(Map<String, dynamic> responseData) {
return User(
id: responseData['id'],
username: responseData['username'],
role: responseData['role'],
token: responseData['token'],
renewalToken: responseData['token'],
);
}
User_provider
class UserProvider extends ChangeNotifier {
User _user = User();
User get user => _user;
void setUser(User? user) {
_user = user!;
notifyListeners();
}
}
Auth_provider
enum Status { NotLoggedIn, LoggedIn, Authenticating, LoggedOut }
class AuthProvider extends ChangeNotifier {
Status _loggedInStatus = Status.NotLoggedIn;
Status get loggedInStatus => _loggedInStatus;
set loggedInStatus(Status value) {
_loggedInStatus = value;
}
static Future<FutureOr> onValue(Response response) async {
var result;
final Map<String, dynamic> responseData = json.decode(response.body);
print(responseData);
if (response.statusCode == 200) {
// now we will create a user model
User authUser = User.fromJson(responseData);
// now we will create shared preferences and save data
UserPreferences().saveUser(authUser);
result = {
'status': true,
'message': 'Successfully registered',
'data': authUser
};
} else {
result = {
'status': false,
'message': 'Successfully registered',
'data': responseData
};
}
return result;
}
Future<Map<String, dynamic>> login(String username, String password) async {
var result;
Map<String, dynamic> loginData = {
'Username': username,
'Password': password,
};
_loggedInStatus = Status.Authenticating;
notifyListeners();
ApiService apiService = ApiService(dio.Dio(), baseUrl: '');
final response = await apiService.login(loginData);
print('${response.toJson()}');
if (response.statusCode == 200) {
User authUser = User(
id: response.userEntity.id,
username: response.userEntity.username,
role: response.userEntity.role,
);
UserPreferences().saveUser(authUser);
_loggedInStatus = Status.LoggedIn;
notifyListeners();
result = {'status': true, 'message': 'Successful', 'user': authUser};
} else {
_loggedInStatus = Status.NotLoggedIn;
notifyListeners();
result = {'status': false, 'message': ''};
}
return result;
}
onError(error) {
print('the error is ${error.detail}');
return {'status': false, 'message': 'Unsuccessful Request', 'data': error};
}
}
Main
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
Future<User> getUserData() => UserPreferences().getUser();
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => AuthProvider()),
ChangeNotifierProvider(create: (_) => UserProvider())
],
child: MaterialApp(
theme: ThemeData(
backgroundColor: Color(0Xfff7f7f5),
fontFamily: 'Cera',
appBarTheme: AppBarTheme(
backgroundColor: Colors.white,
),
),
debugShowCheckedModeBanner: false,
// home: LoginScreen(),
home: FutureBuilder<User>(
future: getUserData(),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return CircularProgressIndicator();
default:
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
else if (snapshot.data!.token == null) {
return LoginScreen();
} else
Provider.of<UserProvider>(context).setUser(snapshot.data);
return TeamsScreen();
}
}),
routes: {
'/auth': (context) => LoginScreen(),
'/teams': (context) => TeamsScreen(),
},
));
}
}
shared_preferences
class UserPreferences {
Future<bool> saveUser(User user) async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('id', user.id as String);
prefs.setString('username', user.username as String);
prefs.setString('role', user.role as String);
prefs.setString('token', user.token as String);
return saveUser(user);
}
Future<User> getUser() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
String id = prefs.getString("id") ?? '';
String username = prefs.getString("username") ?? '';
String role = prefs.getString("role") ?? '';
String token = prefs.getString("token") ?? '';
String renewalToken = prefs.getString("renewalToken") ?? '';
return User(
id: id,
username: username,
role: role,
token: token,
renewalToken: renewalToken);
}
void removeUser() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.remove('id');
prefs.remove('username');
prefs.remove('role');
prefs.remove('token');
}
Future<String?> getToken() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
String? token = prefs.getString("token");
return token;
}
}
That's because the server is returning a json string with a different encoding than application/json. Check your response headers and you should probably see that the Content-Type of your response is not application/json but something else. I had the error when getting a GitLab snippet that was not returned as actual json but as a string.
You have two solutions here :
Ask your server for application/json Content-Type, and if he's a nice server he will comply to your request and return proper json. You can do that by setting HTTP headers either in Dio global options or for a specific request.
In your case it seems you already have tried this option but the server didn't want to comply to your request, so you should probably try option 2.
Add a Dio interceptor that will do the conversion from a String to a Map<dynamic, String> before it's actually treated by Retrofit generated code :
final dio = Dio()
..interceptors.add(
InterceptorsWrapper(
onResponse: (response, handler) {
if (response.requestOptions.method == HttpMethod.GET) {
response.data = jsonDecode(response.data as String);
}
return handler.next(response);
},
),
);
I want to retrieve some data in API, but that's giving an error . How can i get List of all posts
This is my DataModel class:
class DataModel {
DataModel({
required this.id,
required this.title,
required this.body,
});
int id;
String title;
String body;
factory DataModel.fromJson(Map<String, dynamic> json) => DataModel(
id: json["id"],
title: json["title"],
body: json["body"],
);
Map<String, dynamic> toJson() => {
"id": id,
"title": title,
"body": body,
};
}
And this is my get future data function:
Future<DataModel?> getData(context) async {
DataModel? result;
try {
final response = await http.get(
Uri.parse("https://someapi.com/posts"),); // this is example api for security
if (response.statusCode == 200) {
final data = json.decode(response.body);
result = DataModel.fromJson(data);
} else {
// ignore: avoid_print
print("error");
}
} catch (e) {
log(e.toString());
}
return result;
}
That's giving me an error like that:
type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>'
I think in the reponse you are getting a list of items which has to be used like the following
var list = json.decode(response.body);
List<DataModel> result = list.map((i) => DataModel.fromJSON(i)).toList();
return result;
And the method will return
Future<List<DataModel>>?
I'm trying to show my json response after user login. It successfully displaying response in my app when user put correct info. But the app getting crashed when user putting wrong credentials
Here is my json response when user put wrong info. It should displaying Status=0 in my app display(or whatever response I want to display
I/flutter (16426): {"Status":"0","Message":"Wrong Password provided","UserData":null}
Here is my API call when user press the login button
Future<void> login() async{
var jsonResponse = null;
if (passwordontroller.text.isNotEmpty && emailController.text.isNotEmpty) {
var response = await http.post(Uri.parse("http://jhhjhjhjhjhjhj"),
body: ({
'LoginId': emailController.text,
'Password': passwordontroller.text
}));
if (response.statusCode == 200) {
print("Correct");
print(response.body);
jsonResponse = json.decode(response.body.toString());
print(jsonResponse);
Navigator.push(context, MaterialPageRoute(builder: (context)=>AfterLoginResPage(response: ApiResponse.fromJson(jsonResponse))));
}
else {
print("Wronggooooooooooooooooooooooooooo");
print(response.body);
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("Invalid credentials")));
}
} else {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("Blank field is not allowed")));
}
}
My Model class
class ApiResponse {
ApiResponse({
required this.status,
required this.message,
required this.userData,
});
String status;
String message;
UserData userData;
factory ApiResponse.fromJson(Map<String, dynamic> json) => ApiResponse(
status: json["Status"],
message: json["Message"],
//userData: UserData.fromJson(json["UserData"]),
userData: json["UserData"] == null? null:UserData.fromJson(json["UserData"]), //======== Updated
);
}
class UserData {
UserData({
required this.name,
required this.encUserId,
});
String name;
String encUserId;
factory UserData.fromJson(Map<String, dynamic> json) => UserData(
name: json["Name"],
encUserId: json["EncUserId"],
);
}
And then here I'm displaying my response which is successfully getting executed when User putting correct credentials. but got crashed when putting wrong credentials
children: [
Text("Status: ${widget.response.status}"),
Text("Message: ${widget.response.message}"),
one more problem I'm facing ,here im able to display status and message What If I want to display Name & EncUserId also?.
here is my json response in postman after putting right info
{
"Status": "1",
"Message": "You are Logged in successfully",
"UserData": {
"Name": "tuhinroy881#gmail.com",
"EncUserId": "bbA/HajfPdswT0fhhiMvEg=="
}
}
.
Since null safety is enabled, you need to change UserData userData to UserData? userData; and userData: json["UserData"] == null? null:UserData.fromJson(json["UserData"] as Map<String, dynamic>)
Your problem is that you are trying to parse UserData while your error response doesn't have any UserData related information.
class ApiResponse {
ApiResponse({
required this.status,
required this.message,
required this.userData,
});
String status;
String message;
UserData? userData;
factory ApiResponse.fromJson(Map<String, dynamic> json) => ApiResponse(
status: json["Status"],
message: json["Message"],
userData: json["UserData"] == null? null:UserData.fromJson(json["UserData"]),
);
}
Am trying to get a data from a json url but i get the error
Unhandled Exception: type 'List' is not a subtype of type 'SubJsonModel'
main.dart
final String url = 'https://raw.githubusercontent.com/BrightCode1/ohms-json/master/categories.json';
List<JsonModel> myModel = [];
#override
void initState() {
// TODO: implement initState
super.initState();
loadData();
}
loadData() async {
var res = await http.get(url, headers: {"Accept":"application/json"});
if(res.statusCode == 200) {
String resBody = res.body;
var jsonDecode = json.decode(resBody);
for(var data in jsonDecode) {
myModel.add(JsonModel(data['cat_id'], data['category'], data['cat_subcategory']));
setState(() {});
}
print(myModel[1].subCat.name);
}else {
print("Something went wrong!");
}
}
model.dart
class JsonModel {
final String id;
final String category;
SubJsonModel subCat;
JsonModel(this.id, this.category, this.subCat);
}
class SubJsonModel {
final String name;
final String image;
SubJsonModel(this.name, this.image);
}
please how do i solve this
So here what I do first create a model class with the help of this online tool. And then changed code like first save subcategory in one list and then passed it to the main list and then print
Here is my loadData() method
final String url =
'https://raw.githubusercontent.com/BrightCode1/ohms-json/master/categories.json';
List myModel = [];
loadData() async {
var res = await http.get(url, headers: {"Accept": "application/json"});
if (res.statusCode == 200) {
String resBody = res.body;
var jsonDecode = json.decode(resBody);
for (var data in jsonDecode) {
List<CatSubcategory> subCate = []; // Set a emoty list of CatSubcategory
data['cat_subcategory'].map((x) { // Here parsed the cat_subcategory data and simply add it into list
return subCate.add(
CatSubcategory(subName: x['sub_name'], subImage: x['sub_image']));
}).toList(); // and this done for we get map data so convert this data toList();
myModel.add(JsonModel(
category: data['category'],
catId: data['cat_id'],
catIcon: data['cat_icon'],
catSubcategory: subCate));
setState(() {});
}
print(myModel[0].catSubcategory[0].subName);
} else {
print("Something went wrong!");
}
}
here is my model class
class JsonModel {
JsonModel({
this.category,
this.catId,
this.catIcon,
this.catSubcategory,
});
String category;
String catId;
String catIcon;
List<CatSubcategory> catSubcategory;
factory JsonModel.fromJson(Map<String, dynamic> json) => JsonModel(
category: json["category"],
catId: json["cat_id"],
catIcon: json["cat_icon"],
catSubcategory: List<CatSubcategory>.from(
json["cat_subcategory"].map((x) => CatSubcategory.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"category": category,
"cat_id": catId,
"cat_icon": catIcon,
"cat_subcategory":
List<dynamic>.from(catSubcategory.map((x) => x.toJson())),
};
}
class CatSubcategory {
CatSubcategory({
this.subName,
this.subImage,
});
String subName;
String subImage;
factory CatSubcategory.fromJson(Map<String, dynamic> json) => CatSubcategory(
subName: json["sub_name"],
subImage: json["sub_image"],
);
Map<String, dynamic> toJson() => {
"sub_name": subName,
"sub_image": subImage,
};
}
You can use https://app.quicktype.io/ to create the model.dart from a json.
To parse this JSON data, do
final pieSingleChartInfo = pieSingleChartInfoFromJson(jsonString);
import 'dart:convert';
List<PieSingleChartInfo> pieSingleChartInfoFromJson(String str) => List<PieSingleChartInfo>.from(json.decode(str).map((x) => PieSingleChartInfo.fromJson(x)));
String pieSingleChartInfoToJson(List<PieSingleChartInfo> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class PieSingleChartInfo {
PieSingleChartInfo({
this.category,
this.catId,
this.catIcon,
this.catSubcategory,
});
String category;
String catId;
String catIcon;
List<CatSubcategory> catSubcategory;
factory PieSingleChartInfo.fromJson(Map<String, dynamic> json) => PieSingleChartInfo(
category: json["category"],
catId: json["cat_id"],
catIcon: json["cat_icon"] == null ? null : json["cat_icon"],
catSubcategory: List<CatSubcategory>.from(json["cat_subcategory"].map((x) => CatSubcategory.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"category": category,
"cat_id": catId,
"cat_icon": catIcon == null ? null : catIcon,
"cat_subcategory": List<dynamic>.from(catSubcategory.map((x) => x.toJson())),
};
}
class CatSubcategory {
CatSubcategory({
this.subName,
this.subImage,
});
String subName;
String subImage;
factory CatSubcategory.fromJson(Map<String, dynamic> json) => CatSubcategory(
subName: json["sub_name"],
subImage: json["sub_image"],
);
Map<String, dynamic> toJson() => {
"sub_name": subName,
"sub_image": subImage,
};
}
I noted a few issues and corrected them based on the information you provided.
Read the comments. Add a sample response body to the question.
final String url =
'https://raw.githubusercontent.com/BrightCode1/ohms-json/master/categories.json';
List<JsonModel> myModel = [];
#override
void initState() {
// TODO: implement initState
super.initState();
loadData();
}
loadData() async {
var res = await http.get(url, headers: {"Accept": "application/json"});
if (res.statusCode == 200) {
String resBody = res.body;
var jsonDecode = json.decode(resBody);
for (var data in jsonDecode) {
// first create SubJsonModel object
var subCat = SubJsonModel(
data['cat_subcategory']['name'], data['cat_subcategory']['image']);
//use subCat to create JsonModel
myModel.add(JsonModel(data['cat_id'], data['category'], subCat));
setState(() {});
}
print(myModel[1].subCat.name);
} else {
print("Something went wrong!");
}
}
I have this code where am able to get values from an online json data and print its value
main.dart
final String url = 'https://raw.githubusercontent.com/BrightCode1/ohms-json/master/categories.json';
List<JsonModel> myModel = [];
List<CatSubcategory> subCate = [];
int localInt;
#override
void initState() {
// TODO: implement initState
super.initState();
localInt = 0;
loadData(localInt);
}
loadData(int dataInt) async {
var res = await http.get(url, headers: {"Accept": "application/json"});
if (res.statusCode == 200) {
String resBody = res.body;
var jsonDecode = json.decode(resBody);
for (var data in jsonDecode) {
data['cat_subcategory'].map((x) {
return subCate.add(
CatSubcategory(subName: x['sub_name'], subImage: x['sub_image']));
}).toList();
myModel.add(JsonModel(
category: data['category'],
catId: data['cat_id'],
catIcon: data['cat_icon'],
catSubcategory: subCate));
setState(() {});
}
print(myModel[dataInt].catSubcategory.length);
} else {
print("Something went wrong!");
}
}
my model.dart
class JsonModel {
JsonModel({
this.category,
this.catId,
this.catIcon,
this.catSubcategory,
});
String category;
String catId;
String catIcon;
List<CatSubcategory> catSubcategory;
factory JsonModel.fromJson(Map<String, dynamic> json) => JsonModel(
category: json["category"],
catId: json["cat_id"],
catIcon: json["cat_icon"],
catSubcategory: List<CatSubcategory>.from(
json["cat_subcategory"].map((x) => CatSubcategory.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"category": category,
"cat_id": catId,
"cat_icon": catIcon,
"cat_subcategory":
List<dynamic>.from(catSubcategory.map((x) => x.toJson())),
};
}
class CatSubcategory {
CatSubcategory({
this.subName,
this.subImage,
});
String subName;
String subImage;
factory CatSubcategory.fromJson(Map<String, dynamic> json) => CatSubcategory(
subName: json["sub_name"],
subImage: json["sub_image"],
);
Map<String, dynamic> toJson() => {
"sub_name": subName,
"sub_image": subImage,
};
}
The only problem am having now is that when I try to print the length on the subcategory of the first list it gives me 24 instead of 6 and i printed it like this myModel[dataInt].catSubcategory.length. The dataInt is 0 which means it's supposed to print out the length of the children("cat_subcategory") with category of Design & Creativity but it's printing all the other children of the other lis. So please how do i go about this. And if you need more explanation tell me
I would avoid writing your own model from scratch if you already know the schema of your json.
Just use something like https://app.quicktype.io/ just paste your json and you will get
import 'dart:convert';
class Root {
Root({
this.category,
this.catId,
this.catIcon,
this.catSubcategory,
});
String category;
String catId;
String catIcon;
List<CatSubcategory> catSubcategory;
factory Root.fromJson(Map<String, dynamic> json) => Root(
category: json["category"],
catId: json["cat_id"],
catIcon: json["cat_icon"] == null ? null : json["cat_icon"],
catSubcategory: List<CatSubcategory>.from(json["cat_subcategory"].map((x) => CatSubcategory.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"category": category,
"cat_id": catId,
"cat_icon": catIcon == null ? null : catIcon,
"cat_subcategory": List<dynamic>.from(catSubcategory.map((x) => x.toJson())),
};
}
class CatSubcategory {
CatSubcategory({
this.subName,
this.subImage,
});
String subName;
String subImage;
factory CatSubcategory.fromJson(Map<String, dynamic> json) => CatSubcategory(
subName: json["sub_name"],
subImage: json["sub_image"],
);
Map<String, dynamic> toJson() => {
"sub_name": subName,
"sub_image": subImage,
};
}
and then you should be good to just
loadData(int dataInt) async {
var res = await http.get(url, headers: {"Accept": "application/json"});
if (res.statusCode == 200) {
String resBody = res.body;
var list = json.decode(resBody) as List;
List<Root> items = list.map((i)=>Root.fromJson(i)).toList();
print(items[0].catSubcategory.length);
}
} else {
print("Something went wrong!");
}
}
https://repl.it/talk/share/Sample/118111