Error when trying to decode json with Iterable in Flutter - json

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

Related

How can I fetch data in API without giving this error

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

Create POST request with Int key value, status code returns 422 or 415

At first, I was confused about sending an integer value to the key id. Then an error will appear type 'int' is not a subtype of type 'String' in type cast.
After a long time of fixing it, I finally managed to fix the previous error with a code like the following:
class UserData with ChangeNotifier {
Map<String, dynamic> _map = {};
bool _error = false;
String _errorMessage = '';
Map<String, dynamic> get map => _map;
bool get error => _error;
String get errorMessage => _errorMessage;
Future<void> get fetchData async {
final Map<String, dynamic> userBody = {
'id': 1,
'username': 'bunn1est',
};
String _body = jsonEncode(userBody);
final response = await http.post(
Uri.parse('https://*******'),
headers: {
"Accept": "application/json",
"content-type": "application/json",
},
body: _body,
);
if (response.statusCode <= 1000) {
try {
_map = jsonDecode(response.body);
_error = false;
} catch (e) {
_error = true;
_errorMessage = e.toString();
_map = {};
}
} else {
_error = true;
_errorMessage = "Error: It would be your internet connection";
_map = {};
}
notifyListeners();
}
void initialValues() {
_map = {};
_error = false;
_errorMessage = "";
notifyListeners();
}
}
The above code works fine, but I get the status code 422 instead. And then I get the error status code 415 if I try to remove headers inside http.post
headers: {
"Accept": "application/json",
"content-type": "application/json",
},
Is there something wrong with my class model, or is the error happening because it's from the server-side?
If the error status code 422 shows because of my code error, which part should I fix?
EDIT
I've tried it on postman, and it works fine. I still haven't figured out how to store the key value with the Integer data type
Just modify this code
final Map<String, dynamic> userBody = {
'id': 1,
'username': 'bunn1est',
};
String _body = jsonEncode(userBody);
with this
int id = 1;
final _body = {
'id': id.toString(),
'username': 'bunn1est',
};

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

_CastError (type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'List<dynamic>' in type cast)

Want to ask again ... try implementing the data API stored in a local database ...
the form of the JSON API The object in which there is a JSON Array ... there was an error when wanting to load data from the API to Local database ... roughly this is an error because of "the wrong model or what
Api Service
class MealApiProvider {
Future<List<Categories>> getAllMeal() async {
var url = "https://www.themealdb.com/api/json/v1/1/categories.php";
Response response = await Dio().get(url);
print("Hasil Respon ${response.data}");
return (response.data as List).map((employee) {
print('Inserting $employee');
DBProvider.db.insertMeals(Categories.fromJson(employee));
}).toList();
}
}
Model
class DataMeal {
final List<Categories> categories;
DataMeal({this.categories});
#override
String toString() {
return 'DataMeal{categories: $categories}';
}
factory DataMeal.fromJson(Map<String, dynamic> json) {
return DataMeal(
categories: List<Categories>.from(
json["categories"].map(
(categories) {
return Categories.fromJson(categories);
},
),
),
);
}
Map<String, dynamic> toJson() => {
"categories": List<dynamic>.from(
categories.map(
(x) => x.toJson(),
),
),
};
}
Local DB
initDB() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
final String path = join(documentsDirectory.path, '$nameDatabase');
print('insert database $path');
return await openDatabase(path, version: 1, onOpen: (db) {},
onCreate: (Database db, int version) async {
await db.execute('CREATE TABLE $nameTable('
'idCategory,'
'strCategory TEXT,'
'strCategoryThumb TEXT,'
'strCategoryDescription TEXT'
')');
});
}
insertMeals(DataMeal newMeal) async {
await deleteAllMeal();
final Database db = await database;
final res = await db.insert("$nameTable", newMeal.toJson());
print("inserting data $res");
return res;
}
Error
return (response.data as List).map((employee)
Respon Data
Your response contains map at the begining !
Try this
class MealApiProvider {
Future<List<Categories>> getAllMeal() async {
var url = "https://www.themealdb.com/api/json/v1/1/categories.php";
Response response = await Dio().get(url);
print("Hasil Respon ${response.data}");
//***Change below line****
return (response.data['categories'] as List).map((employee) {
print('Inserting $employee');
DBProvider.db.insertMeals(Categories.fromJson(employee));
}).toList();
}
}
instead of
class MealApiProvider {
Future<List<Categories>> getAllMeal() async {
var url = "https://www.themealdb.com/api/json/v1/1/categories.php";
Response response = await Dio().get(url);
print("Hasil Respon ${response.data}");
//*** I change the below line !
return (response.data as List).map((employee) {
print('Inserting $employee');
DBProvider.db.insertMeals(Categories.fromJson(employee));
}).toList();
}
}

how can i make post method in flutter?

How can i make post method in flutter for json like this
{
"app_id": "3djdjkdjde",
"include_external_user_ids": ["88"],
"contents": {"en": "your order is created"}
}
as you see its json inside json my problem in contents it's has a json as its value
i made this model with post method but i don't know how can i parse content you can see i make it's value null for now
it's okay if contents with static message no need for dynamic value in this time
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
Notifications notificationsFromJson(String str) => Notifications.fromJson(json.decode(str));
String notificationsToJson(Notifications data) => json.encode(data.toJson());
class Notifications {
String appId;
List<String> includeExternalUserIds;
Contents contents;
Notifications({
this.appId,
this.includeExternalUserIds,
this.contents,
});
factory Notifications.fromJson(Map<String, dynamic> json) => new Notifications(
appId: json["app_id"],
includeExternalUserIds: new List<String>.from(json["include_external_user_ids"].map((x) => x)),
contents: Contents.fromJson(json["contents"]),
);
Map<String, dynamic> toJson() => {
"app_id": appId,
"include_external_user_ids": new List<dynamic>.from(includeExternalUserIds.map((x) => x)),
"contents": contents.toJson(),
};
static Future<bool> postNotification(serviceUri, notificationData) async {
var client = new http.Client();
bool result = false;
try {
final Map<String, String> _notificationData = {
'app_id': notificationData['app_id'].toString(),
'include_external_user_ids': orderData['include_external_user_ids'].toString(),
"contents": null,
};
await client.post(serviceUri,
body: json.encode(_notificationData),
headers: { 'Authorization' : 'Bearer ' + notificationData['Token'], "Content-Type": "application/json"}
)
.then((http.Response response) {
var responseModel = json.decode(response.body);
if(responseModel != null && responseModel['status'] == true) {
result = true;
} else {
result = false;
}
});
}
catch(e) {
result = false;
}
finally {
client.close();
}
return result;
}
}
class Contents {
String en;
Contents({
this.en,
});
factory Contents.fromJson(Map<String, dynamic> json) => new Contents(
en: json["en"],
);
Map<String, dynamic> toJson() => {
"en": en,
};
}
thanks
Future<Map<String, dynamic>> postRequest(String url, Map jsonMap) async{
print('$url , $jsonMap');
HttpClient httpClient = new HttpClient();
HttpClientRequest request = await httpClient.postUrl(Uri.parse(url));
request.headers.set('content-type', 'application/json');
request.add(utf8.encode(json.encode(jsonMap)));
HttpClientResponse response = await request.close();
String reply = await response.transform(utf8.decoder).join();
print(reply);
httpClient.close();
Map<String, dynamic>map = json.decode(reply);
return map;
}
Add this http: ^0.12.0+1 in your pubspec.yaml file