Bool with json in flutter - json

Hello I am trying to put the variable 'select' to fetch the bool value from a Json file I am not able to do anyone can help me (there is no code all I can get text but I can’t get bool). Thank you.
final _toDoController = TextEditingController();
Map<String, dynamic> _toDoList = Map(); //change this.
void initState() {
super.initState();
_readData().then((data) {
setState(() {
_toDoList = json.decode(data);
});
});
}
void _addToDo() {
setState(() {
Map<String, dynamic> newToDo = Map();
newToDo['verificar'] = true;
_toDoList.addAll(newToDo);
_saveData();
});
}
Widget build(BuildContext context) {
bool selected = _toDoList['verificar'];
return Scaffold(
...
),
body: Container(
color: selected ? Colors.green.withOpacity(0.90) : Colors.deepOrangeAccent.withOpacity(0.90),
...
),
);
}
Future<File> _getFile() async {
final directory = await getApplicationDocumentsDirectory();
return File("${directory.path}/data.json");
}
Future<File> _saveData() async {
String data = json.encode(_toDoList);
final file = await _getFile();
return file.writeAsString(data);
}
Future<String> _readData() async {
try {
final file = await _getFile();
return file.readAsString();
} catch (e) {
return null;
}}}

The problem is the type of list you are using.
List _toDoList = []; //this returns an index based list.
Map<String, dynamic> newTodo = Map(); //this list returns a list with a key and value pair
The solution is to either change _toDoList from index based List to a Map, or access the list using an index.
Map<String, dynamic> _toDoList = Map(); //change _toDoList to this
_toDoList.addAll(newToDo); //change to this
bool selected = _toDoList['verificar'] //this now works
or, with current code as it is, below works.
bool selected _toDoList[0]['verificar'];
Hint:
Print out the run type of a list or variable to see what it is, then it becomes easier to deal access it.
print('a: ${_toDoList.runtimeType} : $_toDoList');
print('b: ${_toDoList[0].runtimeType} : ${_toDoList[0]}');
print('c: ${_toDoList[0]['verificar']}');
Map<String, dynamic> newToDo = Map();
newToDo['verificar'] = true;
Map<String, dynamic> _toDoList2 = Map();
_toDoList2.addAll(newToDo);
print('d: ${_toDoList2.runtimeType} : ${_toDoList2['verificar']}');
and see output, which tells you what type of list this is:
I/flutter (11261): a: List<dynamic> : [{verificar: true}]
I/flutter (11261): b: _InternalLinkedHashMap<String, dynamic> : {verificar: true}
I/flutter (11261): c: true
I/flutter (11261): d: _InternalLinkedHashMap<String, dynamic> : true
In summary, below works
Map<String, dynamic> _toDoList = Map(); //change this.
void initState() {
super.initState();
_readData().then((data) {
setState(() {
_toDoList = json.decode(data);
});
});
}
void _addToDo() {
setState(() {
Map<String, dynamic> newToDo = Map();
newToDo['verificar'] = true;
_toDoList.addAll(newToDo);
_saveData();
});
}
#override
Widget build(BuildContext context) {
bool selected = _toDoList[verificar];

Related

Getting null instead of List of strings flutter json

I'm making a recipes app that request the data form edamam Api and shows it in a listview.builder i have home screen class that make the request and shows the data
import 'package:flutter/material.dart';
import 'package:flutter_application_1/info_screen.dart';
import 'package:flutter_application_1/recipes.dart';
import 'dart:convert' as cnv;
import 'package:http/http.dart' as http;
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
_HomeScreen createState() => _HomeScreen();
}
class _HomeScreen extends State<HomeScreen> {
//List<MissedIngredients>? missedIngredients;
List<Recipe>? results;
int path = 0;
int? numberOfIngredants;
int numberOfRequestedRecipes = 3;
String? foodName;
#override
void initState() {
// TODO: implement initState
super.initState();
getData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Food recipe api'),
),
body: results == null
? Center(
child: CircularProgressIndicator(),
)
: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Card(
child: ListTile(
title: Text(results![index].label.toString()),
leading: Image.network(results![index].image.toString()),
onTap: () {
setState(() {
foodName = results![index].label.toString();
print(foodName);
});
},
));
},
itemCount: numberOfRequestedRecipes),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add_circle),
onPressed: () {
numberOfRequestedRecipes = numberOfRequestedRecipes + 10;
setState(() {
getData();
});
},
),
);
}
Future<void> getData() async {
http.Response res = await http.get(Uri.parse(
'https://api.edamam.com/api/recipes/v2?type=public&q=pizza&app_id=4dd9eafd&app_key=f2fa2c38ec16944f522dc9b734424cf4'));
print(res.body);
List<dynamic> body = cnv.jsonDecode(res.body)['hits'];
results = body.map((dynamic item) => Recipe.fromJson(item)).toList();
setState(() {});
}
}
and a recipes class that analyze the data so i can show it in the home screen
class recipes {
int ?from;
int ?to;
int ?count;
Links ?lLinks;
List<Hits> ?hits;
recipes({this.from, this.to, this.count, this.lLinks, this.hits});
recipes.fromJson(Map<String, dynamic> json) {
from = json['from'];
to = json['to'];
count = json['count'];
lLinks = json['_links'] != null ? new Links.fromJson(json['_links']) : null;
if (json['hits'] != null) {
hits = <Hits>[];
json['hits'].forEach((v) {
hits!.add(new Hits.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['from'] = this.from;
data['to'] = this.to;
data['count'] = this.count;
if (this.lLinks != null) {
data['_links'] = this.lLinks!.toJson();
}
if (this.hits != null) {
data['hits'] = this.hits!.map((v) => v.toJson()).toList();
}
return data;
}
}
class Links {
Next ? next;
Links({required this.next});
Links.fromJson(Map<String, dynamic> json) {
next = (json['next'] != null ? new Next.fromJson(json['next']) : null)!;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.next != null) {
data['next'] = this.next!.toJson();
}
return data;
}
}
class Next {
String ?href;
String ?title;
Next({this.href, this.title});
Next.fromJson(Map<String, dynamic> json) {
href = json['href'];
title = json['title'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['href'] = this.href;
data['title'] = this.title;
return data;
}
}
class Hits {
Recipe ? recipe;
Links ? lLinks;
Hits({this.recipe, this.lLinks});
Hits.fromJson(Map<String, dynamic> json) {
recipe =
json['recipe'] != null ? new Recipe.fromJson(json['recipe']) : null;
lLinks = json['_links'] != null ? new Links.fromJson(json['_links']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.recipe != null) {
data['recipe'] = this.recipe!.toJson();
}
if (this.lLinks != null) {
data['_links'] = this.lLinks!.toJson();
}
return data;
}
}
class Recipe {
String ?uri;
String ?label;
String ?image;
String ?source;
String ?url;
String ?shareAs;
int ?yield;
Recipe(
{this.uri,
this.label,
this.image,
this.source,
this.url,
this.shareAs,
this.yield,
});
Recipe.fromJson(Map<String, dynamic> json) {
uri = json['uri'];
label = json['label'];
image = json['image'];
source = json['source'];
url = json['url'];
shareAs = json['shareAs'];
yield = json['yield'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['uri'] = this.uri;
data['label'] = this.label;
data['image'] = this.image;
data['source'] = this.source;
data['url'] = this.url;
data['shareAs'] = this.shareAs;
data['yield'] = this.yield;
return data;
}
}
class Ingredients {
String? text;
double? weight;
String? foodCategory;
String? foodId;
String? image;
Ingredients(
{this.text, this.weight, this.foodCategory, this.foodId, this.image});
Ingredients.fromJson(Map<String, dynamic> json) {
text = json['text'];
weight = json['weight'];
foodCategory = json['foodCategory'];
foodId = json['foodId'];
image = json['image'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['text'] = this.text;
data['weight'] = this.weight;
data['foodCategory'] = this.foodCategory;
data['foodId'] = this.foodId;
data['image'] = this.image;
return data;
}
}
but when I run the app all I get is a null value so what is the problem
thank you for your valuable time!
Hi the Simplest Solution for your problem is to use a FutureBuilder
If you use the Widget build,
the method will run simultaneous with the init method,due to which you might receive null values even when values are in process of fetching . So use a future builder of type bool and use only when there's data !=null.

Flutter json Expected a value of type 'List<dynamic>', but got one of type ''

Hi i am making a recipes app that shows the name of the food and the image of it and the ingredants
so i made simple home page that makes the requst and a class that gives me the data i used this url from spooncular.com :
https://api.spoonacular.com/recipes/complexSearch?apiKey=8fe91444f092411fa6011b71fd6e582d&number=1&query=pizza&fillIngredients=true
this the main class
import 'package:flutter/material.dart';
import 'package:flutter_application_1/recipes.dart';
import 'dart:convert' as cnv;
import 'package:http/http.dart' as http;
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
_HomeScreen createState() => _HomeScreen();
}
class _HomeScreen extends State<HomeScreen> {
List<MissedIngredients>? modell;
#override
void initState() {
// TODO: implement initState
super.initState();
getData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Food recipe api'),
),
body: modell == null
? Center(
child: CircularProgressIndicator(),
)
: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Card(
child: ExpansionTile(
title: Text(modell![index].originalName.toString()),
children: [
Text(modell![index].name.toString()),
Container(
child:
Image.network('modell![index].image.toString()'),
)
],
),
);
},
itemCount: modell!.length),
);
}
Future<void> getData() async {
http.Response res = await http.get(Uri.parse('https://api.spoonacular.com/recipes/complexSearch?apiKey=8fe91444f092411fa6011b71fd6e582d&number=1&query=pizza&fillIngredients=true'));
print(res.body);
List<dynamic> body = cnv.jsonDecode(res.body)['missedIngredients'];
modell = body.map((dynamic item) => MissedIngredients.fromJson(item)).toList();
setState(() {});
}
}
this is the recipes class i mdae it with json to dart class website
class recipes {
List<Results> ?results;
int? offset;
int? number;
int? totalResults;
recipes({this.results, this.offset, this.number, this.totalResults});
recipes.fromJson(Map<String, dynamic> json) {
if (json['results'] != null) {
results = <Results>[];
json['results'].forEach((v) {
results!.add(new Results.fromJson(v));
});
}
offset = json['offset'];
number = json['number'];
totalResults = json['totalResults'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.results != null) {
data['results'] = this.results!.map((v) => v.toJson()).toList();
}
data['offset'] = this.offset;
data['number'] = this.number;
data['totalResults'] = this.totalResults;
return data;
}
}
class Results {
int? id;
int? usedIngredientCount;
int? missedIngredientCount;
List<MissedIngredients> ?missedIngredients;
int ?likes;
List<Null>? usedIngredients;
List<Null>? unusedIngredients;
String ?title;
String ?image;
String ?imageType;
Results(
{this.id,
this.usedIngredientCount,
this.missedIngredientCount,
this.missedIngredients,
this.likes,
this.usedIngredients,
this.unusedIngredients,
this.title,
this.image,
this.imageType});
Results.fromJson(Map<String, dynamic> json) {
id = json['id'];
usedIngredientCount = json['usedIngredientCount'];
missedIngredientCount = json['missedIngredientCount'];
if (json['missedIngredients'] != null) {
missedIngredients = <MissedIngredients>[];
json['missedIngredients'].forEach((v) {
missedIngredients!.add(new MissedIngredients.fromJson(v));
});
}
title = json['title'];
image = json['image'];
imageType = json['imageType'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['usedIngredientCount'] = this.usedIngredientCount;
data['missedIngredientCount'] = this.missedIngredientCount;
if (this.missedIngredients != null) {
data['missedIngredients'] =
this.missedIngredients!.map((v) => v.toJson()).toList();
}
data['likes'] = this.likes;
data['title'] = this.title;
data['image'] = this.image;
data['imageType'] = this.imageType;
return data;
}
}
class MissedIngredients {
int ? id;
double? amount;
String ?unit;
String ?unitLong;
String ?unitShort;
String? aisle;
String? name;
String? original;
String? originalString;
String? originalName;
List<String> ?metaInformation;
List<String>? meta;
String ?image;
String? extendedName;
MissedIngredients(
{this.id,
this.amount,
this.unit,
this.unitLong,
this.unitShort,
this.aisle,
this.name,
this.original,
this.originalString,
this.originalName,
this.metaInformation,
this.meta,
this.image,
this.extendedName});
MissedIngredients.fromJson(Map<String, dynamic> json) {
id = json['id'];
amount = json['amount'];
unit = json['unit'];
unitLong = json['unitLong'];
unitShort = json['unitShort'];
aisle = json['aisle'];
name = json['name'];
original = json['original'];
originalString = json['originalString'];
originalName = json['originalName'];
metaInformation = json['metaInformation'].cast<String>();
meta = json['meta'].cast<String>();
image = json['image'];
extendedName = json['extendedName'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['amount'] = this.amount;
data['unit'] = this.unit;
data['unitLong'] = this.unitLong;
data['unitShort'] = this.unitShort;
data['aisle'] = this.aisle;
data['name'] = this.name;
data['original'] = this.original;
data['originalString'] = this.originalString;
data['originalName'] = this.originalName;
data['metaInformation'] = this.metaInformation;
data['meta'] = this.meta;
data['image'] = this.image;
data['extendedName'] = this.extendedName;
return data;
}
}
Note:when i try to use the Results class like the title or the image it works but when i try to use missedingredants class it gives me this error Expected a value of type 'List', but got one of type 'Null'
if you want any further info please ask me I the comments and thank you!
Use below method in your case,
Future<void> getData() async {
http.Response res = await http.get(Uri.parse('https://api.spoonacular.com/recipes/complexSearch?apiKey=8fe91444f092411fa6011b71fd6e582d&number=1&query=pizza&fillIngredients=true'));
print(res.body);
var jsonData = cnv.jsonDecode(res.body);
modell = jsonData['results'][0]['missedIngredients'].map((dynamic item) => MissedIngredients.fromJson(item)).toList();
setState(() {});
}
And when there is multiple data in your "results" list you can find "missedIngredients" list into resultList Array,
Future<void> getData() async {
http.Response res = await http.get(Uri.parse('https://api.spoonacular.com/recipes/complexSearch?apiKey=8fe91444f092411fa6011b71fd6e582d&number=1&query=pizza&fillIngredients=true'));
print(res.body);
var jsonData = cnv.jsonDecode(res.body);
List<Results> resultList = jsonData['results'].map(
(jsonElement) => Results.fromJson(jsonElement)
).toList();
print(resultList[0].missedIngredients.length.toString());
}

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

Why can't i get data value from json - flutter

Am trying to get values from my json file categories.json using flutter but am always getting error or its not showing and I don't really know what is wrong
This is my main.dart
Future<List<Category>> loadData() async {
String jString = await rootBundle.loadString("assets/categories.json");
List<dynamic> jRes = jsonDecode(jString);
List<Category> datas = jRes.map((e) => Category.fromJson(e)).toList();
return datas;
}
Container(
child: FutureBuilder<List<Category>>(
future: loadData(),
builder: (context, data) {
if (data.connectionState != ConnectionState.waiting &&
data.hasData) {
var userList = data.data;
return ListView.builder(
itemCount: userList.length,
itemBuilder: (context, index) {
var userData = userList[index];
return Column(
children: [
Text("Category: ${userData.catName}"),
],
);
});
} else {
return Center(
child: CircularProgressIndicator(),
);
}
})),
and my model.dart
class Category {
String catId;
String catName;
SubCategory subcat;
Category({this.catId, this.catName, this.subcat});
factory Category.fromJson(Map<String, dynamic> json) {
return Category(
catId: json['cat_id'],
catName: json['category'],
subcat: SubCategory.fromJson(json['cat_subcategory']),
);
}
Map<String, dynamic> toJson() {
return {
"cat_id": catId,
"category": catName,
};
}
}
class SubCategory {
String subName, subImage;
SubCategory({this.subName, this.subImage});
factory SubCategory.fromJson(Map<String, dynamic> json) {
return SubCategory(subName: json['sub_name'], subImage: json['sub_image']);
}
Map<String, dynamic> toJson() {
return {
"sub_name": subName,
"sub_image": subImage,
};
}
}
and lastly my categories.json file
[{
"category": "Design & Creativity",
"cat_id": "1",
"cat_subcategory": [
{
"sub_name": "Ads",
"sub_image": "https://images.unsplash.com/photo-1589838017489-9198a27bd040?ixid=MXwxMjA3fDB8MHxzZWFyY2h8Mnx8YWR2ZXJ0aXNlbWVudHxlbnwwfHwwfA%3D%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60"
}
]
}]
//There are more of them
The problem am facing when I run it is that it only shows me the CircularProgressIndicator() in my main.dart and when I remove the if statement, it says Another exception was thrown: NoSuchMethodError: The getter 'length' was called on null. Please how do I go about solving this problem and if you need more explanation then tell me
PS: When I check the loadData() value it says type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>'
EDIT: Thank you all for the answers but what i did was to generate a model using this website model generator
and i was able to get the value
Personally, when I want to load data from json file, I do this:
Future<List<Category>> loadData() async {
List<Category> datas = [];
return rootBundle.loadString("assets/categories.json").then((value) {
List<dynamic> jRes = jsonDecode(value);
jRes.forEach((element) {
datas.add(Category.fromJson(element));
});
return datas;
});
}
Also, in SubCategory class
factory SubCategory.fromJson(Map<String, dynamic> json) {
return SubCategory(subName: json['sub_name'], subImage: json['sub_image']);
}
Your fromJson() require Map<String, dynamic>.
But if you look at your file
"cat_subcategory": [
{
"sub_name": "Ads",
"sub_image": "https://images.unsplash.com/photo-1589838017489-9198a27bd040?ixid=MXwxMjA3fDB8MHxzZWFyY2h8Mnx8YWR2ZXJ0aXNlbWVudHxlbnwwfHwwfA%3D%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60"
}
]
You can see that cat_subcategory is a List
So you are giving a List to your SubCategory.fromJson() instead of a Map.
If you want to give a Map, you can simply give the first index of your list
Your Category.fromJson() become
factory Category.fromJson(Map<String, dynamic> json) {
return Category(
catId: json['cat_id'],
catName: json['category'],
subcat: SubCategory.fromJson(json['cat_subcategory'][0]),
);
}
Change your model.dart class
class Category {
String category;
String catId;
List<CatSubcategory> catSubcategory;
Category({this.category, this.catId, this.catSubcategory});
Category.fromJson(Map<String, dynamic> json) {
category = json['category'];
catId = json['cat_id'];
if (json['cat_subcategory'] != null) {
catSubcategory = new List<CatSubcategory>();
json['cat_subcategory'].forEach((v) {
catSubcategory.add(new CatSubcategory.fromJson(v));
});
}}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['category'] = this.category;
data['cat_id'] = this.catId;
if (this.catSubcategory != null) {
data['cat_subcategory'] =
this.catSubcategory.map((v) => v.toJson()).toList();
}
return data;
}}
class CatSubcategory {
String subName;
String subImage;
CatSubcategory({this.subName, this.subImage});
CatSubcategory.fromJson(Map<String, dynamic> json) {
subName = json['sub_name'];
subImage = json['sub_image'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['sub_name'] = this.subName;
data['sub_image'] = this.subImage;
return data;
}}
And Replace
List<Category> datas = jRes.map((e) => Category.fromJson(e)).toList();
with
List<Category> datas = List<Category>.from(jRes.map((category)=> Category.fromJson(category)));

How to get JSON data from an API in flutter

I'm facing the same issue since i start coding yesterday on my project which has a part of getting some of json data from a given api.
My api link is: http://alkadhum-col.edu.iq/wp-json/wp/v2/posts?_embed
I'm working on flutter SDK and i'm confused why it is not working with me!, my job is to get only link, title, and source_url objects but i cannot get it.
I tried the following code in flutter documentation
https://flutter.dev/docs/cookbook/networking/fetch-data
and after some of modification according to my needs didn't got any data.
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<Post> fetchPost() async {
final response =
await http.get('http://alkadhum-col.edu.iq/wp-json/wp/v2/posts/');
if (response.statusCode == 200) {
// If the call to the server was successful, parse the JSON
return Post.fromJson(json.decode(response.body));
} else {
// If that call was not successful, throw an error.
throw Exception('Failed to load post');
}
}
class Post {
final int id;
String title;
String link;
Post({this.id, this.title, this.link});
factory Post.fromJson(Map<String, dynamic> json) {
return Post(
id: json['id'],
title: json['title'].toString(),
link: json['link'].toString()
);
}
}
void main() => runApp(MyApp(post: fetchPost()));
class MyApp extends StatelessWidget {
final Future<Post> post;
MyApp({Key key, this.post}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text('Fetch Data Example'),
),
body: Center(
child: FutureBuilder<Post>(
future: post,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data.link);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default, show a loading spinner
return CircularProgressIndicator();
},
),
),
),
);
}
}
I only got the meesage below:
Type List dynamic is not a subtype of type Map String, dynamic
Any help will be appreciated.
Thanks in advance.
Your JSON response is of type List<dynamic> but you are taking response in Map String, dynamic but you can do something like this
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:clickmeetplay/iam/user/postbean.dart';
import 'package:http/http.dart' as http;
class PostHome extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(home: Scaffold(body: PostScreen(),),);
}
}
class PostScreen extends StatefulWidget {
#override
_PostScreenState createState() => _PostScreenState();
}
class _PostScreenState extends State<PostScreen> {
List<Post> _postList =new List<Post>();
Future<List<Post> > fetchPost() async {
final response =
await http.get('http://alkadhum-col.edu.iq/wp-json/wp/v2/posts/');
if (response.statusCode == 200) {
// If the call to the server was successful, parse the JSON
List<dynamic> values=new List<dynamic>();
values = json.decode(response.body);
if(values.length>0){
for(int i=0;i<values.length;i++){
if(values[i]!=null){
Map<String,dynamic> map=values[i];
_postList .add(Post.fromJson(map));
debugPrint('Id-------${map['id']}');
}
}
}
return _postList;
} else {
// If that call was not successful, throw an error.
throw Exception('Failed to load post');
}
}
#override
Widget build(BuildContext context) {
return Container();
}
#override
void initState() {
fetchPost();
}
}
Bean class
class Post {
final int id;
String title;
String link;
Post({this.id, this.title, this.link});
factory Post.fromJson(Map<String, dynamic> json) {
return Post(
id: json['id'],
title: json['title'].toString(),
link: json['link'].toString()
);
}
}
You need to change your class. you need to create your class structure as per the JSON response.
class Post {
int id;
String title;
String link;
Post({this.id, this.title, this.link});
factory Post.fromJson(Map<String, dynamic> json) {
return Post(
id: json['id'],
title: title = json['title'] != null ? new Title.fromJson(json['title']) : null;
link: json['link'].toString()
);
}
}
class Title {
String rendered;
Title({this.rendered});
Title.fromJson(Map<String, dynamic> json) {
rendered = json['rendered'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['rendered'] = this.rendered;
return data;
}
}
Then, in your API method. As the response, you are getting is a JSON array. So, take that in a list and cast the response into your JSON class.
Future<List<Post>> fetchPost() async {
final response =
await http.get('http://alkadhum-col.edu.iq/wp-json/wp/v2/posts/');
if (response.statusCode == 200) {
// If the call to the server was successful, parse the JSON
var lst = response.body as List;
return lst.map((d) => Post.fromJson(d)).toList();
} else {
// If that call was not successful, throw an error.
throw Exception('Failed to load post');
}
}
You can always use tools like https://javiercbk.github.io/json_to_dart/ to create Dart classes from complex JSON. Which saves a lot of time.
Try below code:
factory Post.fromMap(Map<String, dynamic> json) {
return Post(
id: json['id'],
title: json['title'].cast<String>(),
link: json['link'].cast<String>()
);
}
**Create Api Class**
class ApiUtils {
static String baseUrl = "http://example/";
}
**Create Model**
class EventModel {
String title;
EventModel({this.title});
EventModel.fromJson(Map<String, dynamic> json) {
title = json['Title'] ?? "";
}
}
**Create Service**
import 'package:http/http.dart' as http;
import 'package:NoticeModel.dart';
import 'dart:convert';
class NoticeService {
bool error = false;
bool loading = true;
var notice;
bool noticeDetailserror = false;
bool noticeetailsloading = true;
Future<void> getNotice(dynamic input) async {
try {
noticeDetailserror = false;
http.Response response = await http.post(ApiUtils.noticeApi,
body: input, headers: {'Content-type': 'application/json'});
Map data = jsonDecode(response.body);
if (data["Status"] == true) {
notice = data["Data"];
notice = notice.map((_data) {
return new NoticeModel.fromJson(_data);
}).toList();
print(notice);
noticeetailsloading = false;
} else {
throw data;
}
} catch (e) {
print(e);
noticeetailsloading = false;
noticeDetailserror = true;
}
}
}
**Main Page**
var body =
json.encode({"IsActive": true, "IsDelete": false, "CompanyId": 18});
List<dynamic> data;
var count = 0;
bool loading = true;
bool error = false;
void getNoticeDetails() async {
setState(() {
error = false;
loading = true;
});
// SharedPreferences prefs = await SharedPreferences.getInstance();
NoticeService instance = NoticeService();
await instance.getNotice(body);
data = instance.notice;
if (instance.noticeDetailserror == false) {
setState(() {
count = data.length;
loading = false;
});
} else {
setState(() {
loading = false;
error = true;
});
Toast.show("Error Getting Data", context,
duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);
}
}
#override
void initState() {
super.initState();
getNoticeDetails();
}
body: loading == true
? LinearProgressIndicator()
: error == true
? RetryWidget(
onRetry: getNoticeDetails,
)
: SafeArea(
SizedBox(
width: 270,
child: Text(
data[index].title ?? "",
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 18,
color: Colors.grey,
fontWeight: FontWeight.bold,
),
),
),
)