How can I fetch data in API without giving this error - json

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>>?

Related

Error when trying to decode json with Iterable in Flutter

I'm trying to get this simple json response in Flutter, but getting this error type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Iterable< dynamic >'. I found some people with the same error but the solutions it's not clearly to me. The error occurs on jsonDecode(response.body);, in debug mode, when reachs the response.body, the exception occurs.
{
"#bom": 4,
"#jantar": 3,
"#paris": 2,
}
My model:
import 'dart:convert';
List<Hashtags> hashtagsFromJson(String str) => List<Hashtags>.from(json.decode(str).map((x) => Hashtags.fromJson(x)));
String hashtagsToJson(List<Hashtags> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Hashtags {
Hashtags({
this.hashtag,
});
int? hashtag;
factory Hashtags.fromJson(Map<String, dynamic> json) => Hashtags(
hashtag: json["hashtag"],
);
Map<String, dynamic> toJson() => {
"hashtag": hashtag,
};
}
and my get method:
Future<List<Hashtags>> getHashtagTop() async {
var url = Uri.parse(baseUrl + 'hashtagTop');
final Map<String, String> dataBody = new Map<String, String>();
dataBody['uid'] = appController.currentUser.value.id.toString();
try {
http.Response response = await http.post(
url,
headers: headers,
body: jsonEncode(dataBody),
);
if (response.statusCode == 200 || response.statusCode == 201) {
Iterable jsonResponse = jsonDecode(response.body);
List<Hashtags> listHashtagTop =
jsonResponse.map((model) => Hashtags.fromJson(model)).toList();
return listHashtagTop;
} else {
return [];
}
} catch (e) {
print("ERRO_______________" + e.toString());
return [];
}
}
So what is missing here?
Change your decoding function to this
final results = [jsonDecode(response.body)];
List<Hashtags> listHashtagTop =
results.map((model) => Hashtags.fromJson(model)).toList();
Try this and let you know

Json Status=0 not displaying

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"]),
);
}

Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'SubJsonModel' - flutter

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!");
}
}

Not getting required value from json list - flutter

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

problem converting json response to object in Flutter

first all sorry about my "engrish"...
I'm trying to consume an own API method with http package in Flutter.
I'm able to get a response from API but I'm having trouble trying to map the response (json) to my custom object called APILoginResponse.
I'm calling the API method like this:
APILoginResponse apiLogin = await api.apiLogin();
but I'm getting a runtime error "dynamic is not subtype of AccessToken".
Here is my API login method:
Future<APILoginResponse> apiLogin() async {
final http.Response response = await http.post(
api_end_point + '/api/Auth/login',
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(
<String, String>{'userName': api_user, 'password': api_password}),
);
if (response.statusCode == 200) {
return APILoginResponse.fromJson(json.decode(response.body));
} else {
throw Exception('Error en login de la API');
}
}
...and here is my APILoginResponse object:
class APILoginResponse {
final AccessToken accessToken;
final String refreshToken;
APILoginResponse({this.accessToken, this.refreshToken});
factory APILoginResponse.fromJson(Map<String, dynamic> json) {
return APILoginResponse(
accessToken: json['accessToken'],
refreshToken: json['refreshToken'],
);
}
}
class AccessToken {
String token;
int expiresIn;
}
error is in the line:
accessToken: json['accessToken']
inside APILoginResponse class.
Here is my json response:
{
"accessToken": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3JvbGUiOiIiLCJzdWIiOiJib3N0b25jcmVkX2NsaWVudGVzIiwianRpIjoiZjBkMzY0ZDMtMmRkNS00NzkzLWE5ZTktMzY1YzJmODNiYmI3IiwiaWF0IjoxNTk0MTMxODAwLCJyb2wiOiJhcGlfYWNjZXNzIiwiaWQiOiIyMzg3YTMzZi1hYzE5LTRhMzYtODcyZC04MTE3MzExZDFjY2IiLCJuYmYiOjE1OTQxMzE3OTksImV4cCI6MTU5NDEzMjM5OSwiaXNzIjoid2ViQXBpIiwiYXVkIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzMTcvLyJ9.PqCPkVct4e4duWFEr63fALZ0h_0x25vsV_GBx336Apw",
"expiresIn": 600
},
"refreshToken": "W6wyiw9xYuC2UaJmyCOYujKIZTs0jAscnfcWTrEyVIk="
}
Any help with this will be appreciated. Thanks!
If you are sure that the returning value is an AccessToken you can try this:
factory APILoginResponse.fromJson(Map<String, dynamic> json) {
return APILoginResponse(
accessToken: (json['accessToken'] as Map<String,dynamic>) as AccessToken ?? null,
refreshToken: json['refreshToken'],
);
}
Change your AccessToken class to this:
class AccessToken {
final Map<String,dynamic> tokenData;
AccessToken(tokenData)
}
well I think #P4yam answer was right but I was getting the same error over and over, so I changed my APILoginResponse class as follow:
class APILoginResponse {
AccessToken accessToken;
String refreshToken;
APILoginResponse({this.accessToken, this.refreshToken});
APILoginResponse.fromJson(Map<String, dynamic> json) {
accessToken = json['accessToken'] != null
? new AccessToken.fromJson(json['accessToken'])
: null;
refreshToken = json['refreshToken'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.accessToken != null) {
data['accessToken'] = this.accessToken.toJson();
}
data['refreshToken'] = this.refreshToken;
return data;
}
}
class AccessToken {
String token;
int expiresIn;
AccessToken({this.token, this.expiresIn});
AccessToken.fromJson(Map<String, dynamic> json) {
token = json['token'];
expiresIn = json['expiresIn'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['token'] = this.token;
data['expiresIn'] = this.expiresIn;
return data;
}
}
and everything works fine now! thanks!