Reputation: 3730
I'm building a flutter app where i have to parse some data from api , i set up everything but i'm receiving this error and i don't know why , i'm newbie to flutter , any help would be appreciated thank you .
E/flutter ( 2725): [ERROR:flutter/shell/common/shell.cc(210)] Dart Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'FoodModel',
{
"categories":[
{
"idCategory":"1",
"strCategory":"Beef",
"strCategoryThumb":"https:\/\/www.site.com\/images\/category\/beef.png",
"strCategoryDescription":"Beef is the
},
{
"idCategory":"2",
"strCategory":"Chicken",
"strCategoryThumb":"https:\/\/www.site.com\/images\/category\/chicken.png",
"strCategoryDescription":"Chicken is
},
{
"idCategory":"3",
"strCategory":"Dessert",
"strCategoryThumb":"https:\/\/www.site.com\/images\/category\/dessert.png",
"strCategoryDescription":"Dessert is a course
},
{
"idCategory":"4",
"strCategory":"Lamb",
"strCategoryThumb":"https:\/\/www.site.com\/images\/category\/lamb.png",
"strCategoryDescription":"Lamb, hogget,
}
]
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
var foodList = new List<FoodModel>();
List<FoodModel> list = new List<FoodModel>();
Future<List<FoodModel>> fetchFoodCategories() async {
var url = "https://www.sitess.com/api/json/v1/1/categories.php";
var response = await http.get(url);
if(response.statusCode == 200) {
foodList.add(json.decode(response.body));
}
return foodList;
}
@override
Widget build(BuildContext context) {
fetchFoodCategories().then((value){
list.addAll(value);
});
class FoodModel {
List<Categories> _categories;
List<Categories> get categories => _categories;
FoodModel({
List<Categories> categories}){
_categories = categories;
}
FoodModel.fromJson(dynamic json) {
if (json["categories"] != null) {
_categories = [];
json["categories"].forEach((v) {
_categories.add(Categories.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
var map = <String, dynamic>{};
if (_categories != null) {
map["categories"] = _categories.map((v) => v.toJson()).toList();
}
return map;
}
}
class Categories {
String _idCategory;
String _strCategory;
String _strCategoryThumb;
String _strCategoryDescription;
String get idCategory => _idCategory;
String get strCategory => _strCategory;
String get strCategoryThumb => _strCategoryThumb;
String get strCategoryDescription => _strCategoryDescription;
Categories({
String idCategory,
String strCategory,
String strCategoryThumb,
String strCategoryDescription}){
_idCategory = idCategory;
_strCategory = strCategory;
_strCategoryThumb = strCategoryThumb;
_strCategoryDescription = strCategoryDescription;
}
Categories.fromJson(dynamic json) {
_idCategory = json["idCategory"];
_strCategory = json["strCategory"];
_strCategoryThumb = json["strCategoryThumb"];
_strCategoryDescription = json["strCategoryDescription"];
}
Map<String, dynamic> toJson() {
var map = <String, dynamic>{};
map["idCategory"] = _idCategory;
map["strCategory"] = _strCategory;
map["strCategoryThumb"] = _strCategoryThumb;
map["strCategoryDescription"] = _strCategoryDescription;
return map;
}
}
Upvotes: 1
Views: 438
Reputation: 3777
From the above json that you provided I have created a sample example for you This is the json you provided.
{
"categories":[
{
"idCategory":"1",
"strCategory":"Beef",
"strCategoryThumb":"https:\/\/www.site.com\/images\/category\/beef.png",
"strCategoryDescription":"Beef is the"
},
{
"idCategory":"2",
"strCategory":"Chicken",
"strCategoryThumb":"https:\/\/www.site.com\/images\/category\/chicken.png",
"strCategoryDescription":"Chicken is "
},
{
"idCategory":"3",
"strCategory":"Dessert",
"strCategoryThumb":"https:\/\/www.site.com\/images\/category\/dessert.png",
"strCategoryDescription":"Dessert is a course"
},
{
"idCategory":"4",
"strCategory":"Lamb",
"strCategoryThumb":"https:\/\/www.site.com\/images\/category\/lamb.png",
"strCategoryDescription":"Lamb, hogget,"
}
]
}
This is the model class for the above json data:
// To parse this JSON data, do
//
// final fooModel = fooModelFromJson(jsonString);
import 'dart:convert';
FooModel fooModelFromJson(String str) => FooModel.fromJson(json.decode(str));
String fooModelToJson(FooModel data) => json.encode(data.toJson());
class FooModel {
FooModel({
this.categories,
});
List<Category> categories;
factory FooModel.fromJson(Map<String, dynamic> json) => FooModel(
categories: List<Category>.from(json["categories"].map((x) => Category.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"categories": List<dynamic>.from(categories.map((x) => x.toJson())),
};
}
class Category {
Category({
this.idCategory,
this.strCategory,
this.strCategoryThumb,
this.strCategoryDescription,
});
String idCategory;
String strCategory;
String strCategoryThumb;
String strCategoryDescription;
factory Category.fromJson(Map<String, dynamic> json) => Category(
idCategory: json["idCategory"],
strCategory: json["strCategory"],
strCategoryThumb: json["strCategoryThumb"],
strCategoryDescription: json["strCategoryDescription"],
);
Map<String, dynamic> toJson() => {
"idCategory": idCategory,
"strCategory": strCategory,
"strCategoryThumb": strCategoryThumb,
"strCategoryDescription": strCategoryDescription,
};
}
And this is the list where the ui is rendered you can make changes according to your need this is a sample.
import 'package:flutter/material.dart';
import 'package:json_parsing_example/model2.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SampleApp(),
debugShowCheckedModeBanner: false,
);
}
}
class SampleApp extends StatefulWidget {
@override
_SampleAppState createState() => _SampleAppState();
}
class _SampleAppState extends State<SampleApp> {
bool _isLoading = false;
List<Category> list = List();
fetchData() async {
setState(() {
_isLoading = true;
});
String data =
await DefaultAssetBundle.of(context).loadString("json/parse.json");
// This is the above where you get the remote data
// Like var response = await http.get('your url');
final fooModel = fooModelFromJson(data);
list = fooModel.categories;
setState(() {
_isLoading = false;
});
}
@override
void initState() {
super.initState();
fetchData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Your heading'),
),
body: Container(
child: _isLoading
? Center(child: CircularProgressIndicator())
: Column(
children: <Widget>[
ListView.builder(
shrinkWrap: true,
itemCount: list.length,
itemBuilder: (context, index) {
return Card(
child: Column(
children: <Widget>[
Text('${list[index].idCategory}'),
Text('${list[index].strCategory}')
],
),
);
})
],
)));
}
}
Let me know if it works
Upvotes: 0
Reputation: 742
The json.decode(response.body)
doesn't provide you the FoodModel class you created mate, you need to use something like var jsonResponse = json.decode(response.body);
and then var categoryList = jsonResponse['categories'];
to get the list of categories
Upvotes: 1
Reputation: 26
The error is occurring because you are trying to add a map in foodList, instead of an object of class FoodModel.
You need to utilize FoodModel.fromJson function from your model. So, in the function fetchFoodCategories, instead of the line:
foodList.add(json.decode(response.body));
you should use:
foodList.add(FoodModel.fromJson(json.decode(response.body)));
Upvotes: 0