Taki
Taki

Reputation: 3730

Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>

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

Answers (3)

Sagar Acharya
Sagar Acharya

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

mehul bisht
mehul bisht

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

Tanzeel Hassan
Tanzeel Hassan

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

Related Questions