How to call nested json data using API in flutter? - json

My JSON looks like this:
{
Info: [
{
c_type_id: "1",
cleaning type: "A Cleaning"
},
{
c_type_id: "2",
cleaning type: "B Cleaning"
},
{
c_type_id: "3",
cleaning type: "C Cleaning"
},
{
c_type_id: "4",
cleaning type: "D Cleaning"
},
{
c_type_id: "5",
cleaning type: "E Cleaning"
},
]
}
and here is the code:
The following code is created by this
Class 1:
class Album {
List<Info> info;
Album({this.info})
Album.fromJson(Map<String, dynamic> json) {
if (json['Info'] != null) {
info = List<Info>.empty();
json['Info'].forEach((v) {
info.add(new Info.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.info != null) {
data['Info'] = this.info.map((v) => v.toJson()).toList();
}
return data;
}
}
class 2:
class Info {
String cTypeId;
String cleaningType;
Info({this.cTypeId, this.cleaningType});
Info.fromJson(Map<String, dynamic> json) {
cTypeId = json['c_type_id'];
cleaningType = json['cleaning type'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['c_type_id'] = this.cTypeId;
data['cleaning type'] = this.cleaningType;
return data;
}
}
This is the error I get when I execute the code:
error: The argument type 'List' can't be assigned to the parameter type 'String'.
Hoping for help!

You should Try below code your problem has been solved ->
Declare your API Call funtion
Future<List<dynamic>> getInfoData() async {
String url = 'https://fillmmaka.com/gigocleanapi/cleanintypes.php';
var response = await http.get(Uri.parse(url), headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
});
return json.decode(response.body)['Info'];
}
Declare your Widget
Center(
child: FutureBuilder<List<dynamic>>(
future: getInfoData(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
var id = snapshot.data[index]['c_type_id'];
var type = snapshot.data[index]['cleaning type'];
return Card(
shape: RoundedRectangleBorder(
side: BorderSide(
color: Colors.green.shade300,
),
borderRadius: BorderRadius.circular(15.0),
),
child: ListTile(
leading: Text(id),
title: Text(type),
),
);
},
),
);
}
return CircularProgressIndicator();
},
),
),
Your Screen look like this ->

What is your goal? What do you want to show on the screen?
For example, do you want to show a list with all the cleaning types?
You are getting this error because the attribute info in your Album class is a List:
class Album {
List<Info> info;
If you want to show the cleaningType of the first info on the list, you may do something like this:
return Text(snapshot.data.info[0].cleaningType);
Just keep in mind this will crash if the info list is empty.

you are trying to access the whole list there just use snapshot.data.info[index].variableName you want to access
and you will be good to go

Related

How can i pass this complex Json MAP Data into flutter Listview

i am new to flutter, and i meet this API with complex "MAP" json. What i want is to display the list of countries with their details in flutter listview, How can i achieve that? Most of answers explain about "LIST" json.
{
"status": "Request is successful",
"message": null,
"data": {
"page": 1,
"last_page": 125,
"page_size": 2,
"countries": [
{
"id": "1",
"attributes": {
"name": "Grenada",
"code": "GD",
"subregion": "Caribbean",
"flag": "https://flagcdn.com/gd.svg",
"postalcode": "",
"latitude": "12.11666666",
"longitude": "-61.66666666",
"createdAt": "2023-01-11T22:15:40.000000Z",
"updatedAt": "2023-01-11T22:15:40.000000Z"
}
},
{
"id": "2",
"attributes": {
"name": "Malaysia",
"code": "MY",
"subregion": "South-Eastern Asia",
"flag": "https://flagcdn.com/my.svg",
"postalcode": "^(\\d{5})$",
"latitude": "2.5",
"longitude": "112.5",
"createdAt": "2023-01-11T22:15:40.000000Z",
"updatedAt": "2023-01-11T22:15:40.000000Z"
}
}
]
}
}
I found this GitHub project with these files json, modelClass Mainclass which relate with the concept but mine is has got one extra braces (map) so i do not know how to achieve the goal.
if there any suggestion or best way to code please help me.
this is how they created in model class but, but it does not work with me.
class Product {
final List<Result> results;
Product({this.results});
factory Product.fromJson(Map<String, dynamic> data) {
var list = data['data']['result'] as List;
List<Result> resultList = list.map((e) => Result.fromJson(e)).toList();
return Product(
results: resultList,
);
}
}
what i have done is
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({super.key});
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
var data_from_link;
getData() async {
final String link = 'myurl';
data_from_link = await http.get(Uri.parse(link), headers: {"Accept": "application/json"});
final res = jsonDecode(data_from_link.body) as Map<String, dynamic>;
final List<Country> list= (res['data']['countries'] as List<dynamic>).map((e) => Country.fromJson(e))
.toList();
}
#override
void initState() {
super.initState();
getData();
}
#override
Widget build(BuildContext context) {
final res = jsonDecode(data_from_link.body) as Map<String, dynamic>;
final List<Country> list= (res['data']['countries'] as List<dynamic>).map((e) => Country.fromJson(e))
.toList();
return ListView.builder(
itemCount: list.length,
itemBuilder: (_, i) => ListTile(
title: Text(
list![i].attributes.name,
),
subtitle: Text(list![i].attributes.code),
)
);
}
}
You can create two classes for Country and Attribute
class Country {
const Country({required this.id, required this.attributes});
/// Creates a Country from Json map
factory Country.fromJson(Map<String, dynamic> json) => Country(
id: json['id'] as String,
attribute:
Attribute.fromJson(json['attributes'] as Map<String, dynamic>),
);
/// A description for id
final String id;
final Attribute attributes;
}
class Attribute {
const Attribute({
required this.name,
required this.code,
required this.createdAt,
required this.updatedAt,
});
/// Creates a Attribute from Json map
factory Attribute.fromJson(Map<String, dynamic> json) => Attribute(
name: json['name'] as String,
code: json['code'] as String,
createdAt: DateTime.parse(json['createdAt'] as String),
updatedAt: DateTime.parse(json['updatedAt'] as String),
);
final String name;
final String code;
final DateTime createdAt;
final DateTime updatedAt;
}
when decoding:
final res = jsonDecode(json) as Map<String, dynamic>;
final List<Country> list = (res['data']['countries'] as
List<dynamic>)
.map((e) => Country.fromJson(e))
.toList();
Thank you but how can i print or call data from country attribute
after decoding because when i try something like Print
(list.country.attribute.name) . I fail. My goal is to display on
Listview
You can use it like this:
ListView.builder(
itemCount: list.length,
itemBuilder: (_, i) => ListTile(
title: Text(
list[i].attributes.name,
),
subtitle: Text(list[i].attributes.code),
)),
UPDATE
import 'package:flutter/material.dart';
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({super.key});
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
late Future<List<Country>> futureList;
Future<List<Country>?> getData() async {
final String link = 'yoururl';
final res = await http
.get(Uri.parse(link), headers: {"Accept": "application/json"});
if (response.statusCode == 200) {
final List<Country> list = (res['data']['countries'] as List<dynamic>)
.map((e) => Country.fromJson(e))
.toList();
return list;
} else {
throw Exception('Failed to fetch data');
}
}
#override
void initState() {
super.initState();
futureList = getData();
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: futureList,
builder: (context, snapshot) {
if (snapshot.hasData) {
final list = snapshot.data;
return ListView.builder(
itemCount: list!.length,
itemBuilder: (_, i) => ListTile(
title: Text(
list![i].attributes.name,
),
subtitle: Text(list![i].attributes.code),
),
);
} else if (snapshot.hasError) {
return const Text('error fetching data');
}
return const CircularProgressIndicator();
},
);
}
}

How to store complex json data in model class in flutter

Here is my code"
I've tried printing values.
I got value in token.
I'm able to iterate through the each value present in API using for each loop but data isn't storing into my model class.
SharedPreferences prefs = await SharedPreferences.getInstance();
final token = prefs.getString("token") ?? null;
final userId = prefs.getInt("id") ?? null;
List<GroupListData> grpDataList = [];
if (token != null) {
String url = "${NetworkRequest.baseUrl}/api/group_list";
var groupRes = await http.post(Uri.parse(url), body: {
"user_id": '$userId'
}, headers: {
//'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer $token',
});
//print(groupRes.body);
if (groupRes.statusCode == 200) {
final rowJsonData = jsonDecode(groupRes.body);
GroupListData groupListData;
List<dynamic> groupLists = rowJsonData['data'];
groupLists.forEach((d) {
print(d['id']);
groupListData = GroupListData(
id: d['id'],
groupName: d["groupName"],
status: d["status"],
createdAt: d["createdAt"],
updatedAt: d["updatedAt"],
);
grpDataList.add(groupListData);
});
for (var d in rowJsonData['data']) {
print(d);
}
} else {
print('grpResp ${groupRes.statusCode}');
}
//print('Token : $token');
} else {
print('token is empty');
}
print(grpDataList);
return grpDataList;
}
here this is my JSON Data
{
"data": [
{
"id": 1,
"group_name": "payroll",
"status": 1,
"created_at": "2021-07-20 08:27:31",
"updated_at": "2021-07-20 10:09:11"
},
{
"id": 2,
"group_name": "New Recuritment",
"status": 1,
"created_at": "2021-07-20 11:21:40",
"updated_at": "2021-07-20 11:21:40"
}
],
"message": "Data Found",
"status": 200
}
here is my model class
i think that there is issue in my model class
i am not able to understand
class GroupListData {
GroupListData({
this.id,
this.groupName,
this.status,
this.createdAt,
this.updatedAt,
});
int? id;
String? groupName;
int? status;
DateTime? createdAt;
DateTime? updatedAt;
factory GroupListData.fromJson(Map<String, dynamic> json) => GroupListData(
id: json["id"],
groupName: json["group_name"],
status: json["status"],
createdAt: DateTime.parse(json["created_at"]),
updatedAt: DateTime.parse(json["updated_at"]),
);
Map<String, dynamic> toJson() => {
"id": id,
"group_name": groupName,
"status": status,
"created_at": createdAt!.toIso8601String(),
"updated_at": updatedAt!.toIso8601String(),
};
}
here is my ui code
FutureBuilder<List<GroupListData>>(
future: getGroupListData(),
builder: (BuildContext context,
AsyncSnapshot<List<GroupListData>> snapshot) {
if (snapshot.data == null) {
return Container(
child: Center(
child: Text('Loading...'),
),
);
}
return ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: snapshot.data!.length,
itemBuilder: (BuildContext context, int index) {
return RoundedCard(
str: '${snapshot.data![index].groupName}', ///.groupName always return null value
onTap: () {
Navigator.push(
context,
PageTransition(
type: PageTransitionType.rightToLeft,
child: FeedPage(feedTitle: 'Marketing Team'),
inheritTheme: true,
ctx: context),
);
print('Marketing card');
});
});
},
),
thanks in advance
You dont need to convert your json to modal by yourself.
if the Flutter SDK < 2.0 (Null safety) then please use this online json converter https://javiercbk.github.io/json_to_dart/
otherwise use this online json Converter for Flutter > 2.0 https://app.quicktype.io/

About Flutter Firestore Rest Api Json Output

{
"documents": [
{
"name": "projects/xxxxx/databases/(default)/documents/blogs/Hao5IboeA6b7ySlmx0qN",
"fields": {
"imgUrl": {
"stringValue": "https://firebasestorage.googleapis.com/v0/b/xxxxxx/o/blogImages%2F72H566888.jpg?alt=media&token=75b75deb-69a3-4019-a82e-335a2d72b52e"
},
"authorName": {
"stringValue": "iki"
},
"title": {
"stringValue": "dd"
},
"desc": {
"stringValue": "ee"
}
},
"createTime": "2020-10-31T08:57:46.799862Z",
"updateTime": "2020-10-31T08:57:46.799862Z"
},
]
}
I am using Firebase Firestore Rest Api. I have the output in json format like above. I created my model using Json to dart. My model is as follows.
class Model {
List<Documents> documents;
Model({this.documents});
Model.fromJson(Map<String, dynamic> json) {
if (json['documents'] != null) {
documents = new List<Documents>();
json['documents'].forEach((v) {
documents.add(new Documents.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.documents != null) {
data['documents'] = this.documents.map((v) => v.toJson()).toList();
}
return data;
}
}
class Documents {
String name;
Fields fields;
String createTime;
String updateTime;
Documents({this.name, this.fields, this.createTime, this.updateTime});
Documents.fromJson(Map<String, dynamic> json) {
name = json['name'];
fields =
json['fields'] != null ? new Fields.fromJson(json['fields']) : null;
createTime = json['createTime'];
updateTime = json['updateTime'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['name'] = this.name;
if (this.fields != null) {
data['fields'] = this.fields.toJson();
}
data['createTime'] = this.createTime;
data['updateTime'] = this.updateTime;
return data;
}
}
......
return jsonModel.map((item) => model.fromJson(item)).toList(); I returned it as but in FutureBuilder it comes as snapshot.data[index].documents.
How do I access the imgUrl, authorName, title, desc fields? I am having difficulty with this kind of mixed json output. Can you help me?
You can make a nested structure listView, and you access to field models.
First way:
return FutureBuilder<List<Document>>(
future: getDocuments(),
builder: (BuildContext context, AsyncSnapshot<List<Document>> snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return buildListView(snapshot.data[index].documents);
},
);
} else {
return Text("error");
}
},
);
And you do sub inner method then draw.
ListView buildListView(List<Documents> documents) {
return ListView.builder(
itemCount: documents.length,
itemBuilder: (context, index) => ListTile(
title: Text(documents[index].name),
leading: Text(documents[index].fields.imgUrl.stringValue),
subtitle: Text(documents[index].fields.desc.stringValue),
),
);
2.You could be convert list to list model with list expand functions.
Future<List<Document>> getDocuments() async {
await Future.delayed(Duration(seconds: 100));
return dummyItems;
}
Future<List<Documents>> getFieldsOnly() async {
final response = await getDocuments();
return response.expand((f) => f.documents).toList();
}
Now, it's all done. You can look at this repo for more details(lib/fire-store-document)

Flutter JSON Nested to Lisview Builder

sorry i have searched on youtube and google but i'm still not getting any clue to parse JSON nested to listview builder.
my json result
[
{
"ID_Type": "1",
"Type": "Food",
"Item": [
{
"SLU_Number": "3",
"SLU_Name": "Food"
}
]
},
{
"ID_Type": "2",
"Type": "Beverages",
"Item": [
{
"SLU_Number": "1",
"SLU_Name": "Non Alcohol"
},
{
"SLU_Number": "2",
"SLU_Name": "Alchohol"
}
]
}
]
i want ID_Type, Type,Item (SLU_Number and SLU Name) throw all value to Listview.builder
thank you.
my code on flutter, i follow some code on youtube and that throw the value to List but i don't how to throw the value to Listview.builder
class Products {
final ID_Type;
final Name_Type;
final Items;
Products({
this.ID_Type,
this.Name_Type,
this.Items,
});
factory Products.fromJson(Map<String, dynamic> json) {
return Products(
ID_Type: json["ID_Type"],
Name_Type: json["Type"],
Items: Item.fromJson(json["Item"]),
);
}
}
class Item {
final SLU_Number;
final SLU_Name;
Item({
this.SLU_Number,
this.SLU_Name,
});
factory Item.fromJson(Map<String, dynamic> json) {
return Item(
SLU_Number: json["SLU_Number"],
SLU_Name: json["SLU_Name"],
);
}
}
here below is my Future to throw all the "json" result to List
//------------------------------Start Syntax for List SLU
final listslu = new List<ListSLU>();
final GlobalKey<RefreshIndicatorState> _refreshlistslu =
GlobalKey<RefreshIndicatorState>();
Future<void> ListSLUs() async {
listslu.clear();
setState(() {
loading = true;
});
try {
final response = await http.get(BaseUrl.ListSLU);
if (response.contentLength == 2) {
} else {
final data = jsonDecode(response.body);
data.forEach((api) {
final b = new ListSLU(
api['ID_Type'].toString(),
api['SLU_Number'].toString(),
api['SLU_Name'].toString(),
);
listslu.add(b);
print(api['SLU_Name'].toString());
});
}
} catch (e) {
print("Error List SLU :");
print(e);
}
}
//------------------------------End Syntax for List Type
after parsing all json result and then all value from json i throw to body
Expanded(
flex: 2,
child: ListView.builder(
itemCount: listslu.length,
itemBuilder: (context,i){
final z = listslu[i];
return GestureDetector(
onTap: (){
},
child: Container(
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Row(
children: <Widget>[
Text(z.SLU_Number +' - '+ z.SLU_Name),
],
),
],
)
],
),
),
);
}
)
),

type _InternalLinkedHashMap<String, dynamic> is not subtype of type List<dynamic>

I am trying to implement a simple news feed app using network call wherein the screen will show the latest stories in a Listview.
With the current code, I am getting a response back from the API (as I see the entire response body in the log) but can't seem to display the data in the UI. I am getting this error :
type _InternalLinkedHashMap<String, dynamic> is not subtype of type List
This is the JSON structure
{
"response": {
"status": "ok",
"userTier": "developer",
"total": 25095,
"startIndex": 1,
"pageSize": 10,
"currentPage": 1,
"pages": 2510,
"orderBy": "relevance",
"results": [
{
"id": "australia-news/2018/aug/13/turnbulls-energy-policy-hangs-in-the-balance-as-euthanasia-debate-given-precedence",
"type": "article",
"sectionId": "australia-news",
"sectionName": "Australia news",
"webPublicationDate": "2018-08-12T18:00:08Z",
"webTitle": "Energy policy hangs in balance, as Senate debates euthanasia",
"webUrl": "https://www.theguardian.com/australia-news/2018/aug/13/turnbulls-energy-policy-hangs-in-the-balance-as-euthanasia-debate-given-precedence",
"apiUrl": "https://content.guardianapis.com/australia-news/2018/aug/13/turnbulls-energy-policy-hangs-in-the-balance-as-euthanasia-debate-given-precedence",
"isHosted": false,
"pillarId": "pillar/news",
"pillarName": "News"
}, {
"id": "media/2018/jun/13/the-rev-colin-morris-obituary-letter",
"type": "article",
"sectionId": "media",
For my understanding, I just want to first display webTitle in the list, and later add other fields (after I understand the network concept clearly), but getting the error mentioned above. This is my complete code :
class MyApp extends StatelessWidget{
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Network Example',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new Scaffold(
appBar: AppBar(
title: new Text('Network Example'),
),
body: new Container(
child: new FutureBuilder<List<News>> (
future: fetchNews(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return new ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Text(snapshot.data[index].newsTitle,
style: new TextStyle(
fontWeight: FontWeight.bold)
),
new Divider()
],
);
}
);
} else if (snapshot.hasError) {
return new Text("${snapshot.error}");
}
return CircularProgressIndicator();
},
),
),
),
);
}
Future<List<News>> fetchNews() async {
final response = await http.get('https://content.guardianapis.com/search?q=debates&api-key=');
print(response.body);
List responseJson = json.decode(response.body.toString());
List<News> newsTitle = createNewsList(responseJson);
return newsTitle;
}
List<News> createNewsList(List data) {
List<News> list = new List();
for (int i = 0; i< data.length; i++) {
String title = data[i]['webTitle'];
News news = new News(
newsTitle: title);
list.add(news);
}
return list;
}
}
class News {
final String newsTitle;
News({this.newsTitle});
factory News.fromJson(Map<String, dynamic> json) {
return new News(
newsTitle: json['webTitle'],
);
}
}
I looked at similar questions before and also went through json structures articles but can't seem to figure out how to resolve this issue.
The problem is, your JSON is not an array. It is an object. But you tried to use it as an array.
You may want to change your createNewsList call to the following:
List responseJson = json.decode(response.body.toString());
List<News> newsTitle = createNewsList(responseJson["response"]["results"]);
Mybe you can try modify this method, like this :
Future<List<News>> fetchNews() async {
final response = await http.get('https://content.guardianapis.com/search?q=debates&api-key=');
print(response.body);
List responseJson = json.decode(response.body.result);
List<News> newsTitle = createNewsList(responseJson);
return newsTitle;
}
You can use this
Map<String, String> stringParams = {};
Or
var stringParams = <String, String>{};