Access up to the "model" key parameter in my listview builder for the provided json format in flutter - json

I want to access up to the "model" key parameter in my listview builder for the provided json format in flutter but I don't know how can I access them
I want to access the child object model
What the json will look like:
[
{
"vehicle": "roadways",
"id": "10000",
"category": {
"500": {
"id": "500",
"name": "Bike",
"icon": "http://example.com/bike.jpg",
"model": [
{
"id": "510",
"name": "Harley"
},
{
"id": "520",
"name": "Kawasaki"
}
]
},
"50": {
"id": "50",
"name": "Car",
"icon": "http://example.com/car.jpg",
}
},
},
{
"vehicle": "waterways",
"id": "20000",
"category": {
"600": {
"id": "600",
"name": "Ship",
"icon": "http://example.com/ship.jpg",
"model": [
{
"id": "610",
"name": "model_1"
},
{
"id": "520",
"name": "model_2"
}
]
},
"700": {
"id": "700",
"name": "model_3",
"icon": "http://example.com/car.jpg",
}
},
}
]

var data = jsonDecode("yourJosnString");
ListView.builder(
itemCount: data.length,
itemBuilder: (context, i) {
var data1 = data[i]["category"];
String firstKey = data1.keys.first;
var model = data1[firstKey];
return Column(
children: [
for (i = 0; i < model.length; i++) ...[
Text(
model["name"],
)
]
],
);
},
),

you should first make an object for this json, like this:
class Vehicle {
final String name;
final VehicleCategory category;
Vehicle({#required this.name, #required this.category});
static List<Vehicle> fromJson(List _list) {
List<Vehicle> result = [];
for (var item in _list) {
var address = Vehicle(
name: item['id'] as String,
category: VehicleCategory.fromJson(
item['category']['500'] as Map<String, Object> ?? {}),
);
result.add(address);
}
return result;
}
}
class VehicleCategory {
final String name;
final String icon;
final List<VehicleModel> model;
VehicleCategory(
{#required this.name, #required this.icon, #required this.model});
static VehicleCategory fromJson(Map<String, Object> _json) {
return VehicleCategory(
name: _json['name'] as String ?? '',
icon: _json['icon'] as String ?? '',
model:
VehicleModel.fromJson(_json['model'] as List ?? []));
}
}
class VehicleModel {
final String name;
final String id;
VehicleModel({#required this.name, #required this.id});
static List<VehicleModel> fromJson(List _list) {
List<VehicleModel> result = [];
for (var item in _list) {
var address = VehicleModel(
name: item['name'] as String,
id: item['id'] as String,
);
result.add(address);
}
return result;
}
}
then use it like this:
List<Vehicle> _list = Vehicle.fromJson(_myJson);
return ListView.builder(
itemCount: _list.length,
itemBuilder: (context, i) {
return Column(
children: [
ListView.builder(
itemCount: _list[i].category.model.length,
itemBuilder: (context, j) {
return Text(_list[i].category.model[j].name);
},
)
],
);
},
);

Related

Parse Array in Object in Array in Dart / Flutter

I have a REST Service I like to consume, but I do not know how to parse that JSON to an Object.
My JSON looks like that:
[
{
"types": {
"KEYWORD": "STRING"
},
"displaynames": {
"KEYWORD": "Keyword"
},
"rows": [
{
"KEYWORD": "Test 1"
},
{
"KEYWORD": "Test 2"
}
]
}
]
That is my object I created from that:
import 'dart:convert';
List<Todo> welcomeFromJson(String str) =>
List<Todo>.from(json.decode(str).map((x) => Todo.fromJson(x)));
String welcomeToJson(List<Todo> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Todo {
Todo({
required this.types,
required this.displaynames,
required this.rows,
});
Displaynames types;
Displaynames displaynames;
List<Displaynames> rows;
factory Todo.fromJson(Map<String, dynamic> json) => Todo(
types: Displaynames.fromJson(json["types"]),
displaynames: Displaynames.fromJson(json["displaynames"]),
rows: List<Displaynames>.from(
json["rows"].map((x) => Displaynames.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"types": types.toJson(),
"displaynames": displaynames.toJson(),
"rows": List<dynamic>.from(rows.map((x) => x.toJson())),
};
}
class Displaynames {
Displaynames({
required this.keyword,
});
String keyword;
factory Displaynames.fromJson(Map<String, dynamic> json) => Displaynames(
keyword: json["KEYWORD"],
);
Map<String, dynamic> toJson() => {
"KEYWORD": keyword,
};
}
I try Loading the JSON and Display like that by using the pull_to_refresh Package.
import 'package:flutter/material.dart';
import 'package:pull_to_refresh_flutter3/pull_to_refresh_flutter3.dart';
import 'dart:convert';
import 'package:user_portal/model/todo.dart';
class TodoRoute extends StatefulWidget {
const TodoRoute({super.key});
#override
State<TodoRoute> createState() => _TodoRouteState();
}
class _TodoRouteState extends State<TodoRoute> {
late List<Todo> todoList = [];
final RefreshController refreshController =
RefreshController(initialRefresh: true);
Future<bool> fetchTodo() async {
const String jsonstr =
'[ { "types": { "KEYWORD": "STRING" }, "displaynames": { "KEYWORD": "Keyword" }, "rows": [ { "KEYWORD": "Test 1" }, { "KEYWORD": "Test 2" } ] }]';
todoList = (json.decode(jsonstr) as List)
.map((data) => Todo.fromJson(data))
.toList();
setState(() {});
return true;
}
#override
Widget build(context) {
return Scaffold(
appBar: AppBar(
title: const Text('Todo'),
),
body: SmartRefresher(
controller: refreshController,
enablePullUp: true,
onRefresh: () async {
final result = await fetchTodo();
if (result) {
refreshController.refreshCompleted();
} else {
refreshController.refreshFailed();
}
},
onLoading: () async {
final result = await fetchTodo();
if (result) {
refreshController.loadComplete();
} else {
refreshController.loadFailed();
}
},
child: ListView.separated(
scrollDirection: Axis.vertical,
itemCount: todoList.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(todoList[0].rows[index].keyword),
);
},
separatorBuilder: (context, index) => const Divider(),
),
),
);
}
}
But the Only Item I get is the Test 1 Item not the Test 2 Item and I do not know where to look further for that Problem.
try this way it's so easy...
add this method in your TOdo model
static List< Todo > fromList(json) {
List< Todo > tempList = [];
try {
json.forEach((element) {
tempList.add(Todo.fromJson(element));
});
return tempList;
} catch (e) {
return tempList;
}
}
change this function
Future<bool> fetchTodo() async {
const String jsonstr =
'[ { "types": { "KEYWORD": "STRING" },
"displaynames": { "KEYWORD": "Keyword" }, "rows": [ {
"KEYWORD": "Test 1" }, { "KEYWORD": "Test 2" }
]
}]';
Map data = json.decode(jsonstr);
todoList = Todo.fromList(data);
setState(() {});
return true;
}
Change your fetchTodo() to this:
Future<bool> fetchTodo() async {
const String jsonstr =
'[ { "types": { "KEYWORD": "STRING" }, "displaynames": { "KEYWORD": "Keyword" }, "rows": [ { "KEYWORD": "Test 1" }, { "KEYWORD": "Test 2" } ] }]';
todoList = welcomeFromJson(jsonstr);//<--- add this
setState(() {});
return true;
}
also change this in asdas class:
factory Todo.fromJson(Map<String, dynamic> json) => Todo(
types: Displaynames.fromJson(json["types"]),
displaynames: Displaynames.fromJson(json["displaynames"]),
rows: json["rows"] != null ? (json["rows"] as List).map((x) => Displaynames.fromJson(x)).toList():[],

Filtering nested JSON response in Flutter

Hello I have a question regarding filtering of nested json response from an API.
Suppose I have this sample JSON response from an API:
{
"results": {
"data": {
"parentName": "Vic",
"parentFamName": "Lo",
"children": [
{
"childName": "Mark",
"childCount": 2,
"grandChildren": [
{
"grandChildName": "Kent",
"grandChildAge": 4,
"isBoy": true,
},
{
"grandChildName": "Chris",
"grandChildAge": 8
"isBoy": true,
}]
},
{
"childName": "Kim",
"childCount": 3,
"grandChildren": [
{
"grandChildName": "Martin",
"grandChildAge": 6,
"isBoy": true,
},
{
"grandChildName": "Thesa",
"grandChildAge": 4
"isBoy": false,
},
{
"grandChildName": "Beck",
"grandChildAge": 2,
"isBoy": false,
}]
}]
}
}
}
then ill be decoding the response by:
final jsonResponse = jsonDecode(jsonString.body);
final parentResponse = jsonResponse['results']['data'];
But before I display it in a ListView.builder,
how do I filter the parenetResponse wherein it will only include "isBoy" = true?
like the final data response to display would be:
{
"results": {
"data": {
"parentName": "Vic",
"parentFamName": "Lo",
"children": [
{
"childName": "Mark",
"childCount": 2,
"grandChildren": [
{
"grandChildName": "Kent",
"grandChildAge": 4,
"isBoy": true,
},
{
"grandChildName": "Chris",
"grandChildAge": 8
"isBoy": true,
}]
},
{
"childName": "Kim",
"childCount": 3,
"grandChildren": [
{
"grandChildName": "Martin",
"grandChildAge": 6,
"isBoy": true,
},
]
}]
}
}
}
Thank you for any help!
First create model class to parse your json:
class ParentModel {
final String parentName;
final List<ChildrenModel> children;
ParentModel({required this.parentName, required this.children});
static ParentModel fromJson(Map<String, dynamic> json) {
var children = json['children'] as List;
return ParentModel(
parentName: json['parentName'],
children: children.map((e) => ChildrenModel.fromJson(e)).toList());
}
}
class ChildrenModel {
final int count;
final String name;
final List<GrandChildModel> grandChildren;
ChildrenModel({
required this.count,
required this.name,
required this.grandChildren,
});
static ChildrenModel fromJson(Map<String, dynamic> json) {
var grandChildren = json["grandChildren"] as List;
return ChildrenModel(
count: json['childCount'],
name: json['childName'],
grandChildren:
grandChildren.map((e) => GrandChildModel.fromJson(e)).toList());
}
}
class GrandChildModel {
final int age;
final String name;
final bool isBoy;
GrandChildModel({required this.age, required this.name, required this.isBoy});
static GrandChildModel fromJson(Map<String, dynamic> json) {
return GrandChildModel(
age: json['grandChildAge'],
name: json['grandChildName'],
isBoy: json['isBoy']);
}
}
then use this to show the boy grandChildren:
class TestParent extends StatefulWidget {
const TestParent({super.key});
#override
State<TestParent> createState() => _TestParentState();
}
class _TestParentState extends State<TestParent> {
#override
Widget build(BuildContext context) {
final parentResponse = jsonResponse['results']!['data'];
var parent = ParentModel.fromJson(parentResponse!);
return Scaffold(
appBar: AppBar(title: Text("Testing")),
body: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: parent.children.length,
itemBuilder: (context, index) {
return ListView.builder(
shrinkWrap: true,
itemCount: parent.children[index].grandChildren.length,
itemBuilder: (context, i) {
var grandChild = parent.children[index].grandChildren[i];
if (grandChild.isBoy) {
return Text(grandChild.name);
} else {
return SizedBox();
}
},
);
},
),
)
],
),
);
}
}
Note that here jsonResponse is your json;
result:
Without making model classes you could simply modify the response like this:
parentResponse['children'] = parentResponse['children']
.map((child) => child
..['grandChildren'] = child['grandChildren']
.where((grandChild) => grandChild['isBoy'] as bool)
.toList())
.toList();

Put JSON Data in Flutter Stacked Chart

I have try to put my JSON data in flutter Stacked Chart.
I already work on simple charts using JSON Data like bar, column, pie, Doughnut charts etc.
I have refer
stacked-column-chart(syncfusion_flutter_charts),
Grouped Bar Chart(charts_flutter)
Stack Overflow Que-Ans
below like my API response/JSON String
[{
"name": "ABC",
"subject": [{
"name": "Math",
"marks": "54"
},
{
"name": "Physics",
"marks": "65"
}
]
},
{
"name": "PQR",
"subject": [{
"name": "Chemistry",
"marks": "53"
},
{
"name": "Biology",
"marks": "22"
},
{
"name": "English",
"marks": "7 "
},
{
"name": "Math",
"marks": "12"
}
]
}, {
"name": "JKL",
"subject": [{
"name": "Chemistry",
"marks": "53"
},
{
"name": "Biology",
"marks": "22"
},
{
"name": "English",
"marks": "79 "
},
{
"name": "Math",
"marks": "12"
},
{
"name": "Physics",
"marks": "72"
}
]
}
]
Or I want below type of graph using JSON Data
Note: Suggest me my JSON string is wrong, you can create your own JSON data and display the output
Using charts_flutter. Please customize it for your usecase its a bare minimum implementation to validate that its working for your json.
import 'package:flutter/material.dart';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
import 'dart:convert';
class StackedBarChart extends StatelessWidget {
final bool animate;
StackedBarChart({this.animate = false});
// EXCLUDE_FROM_GALLERY_DOCS_END
#override
Widget build(BuildContext context) {
String jsonString = '[{"name":"ABC","subject":[{"name":"Math","marks":"54"},{"name":"Physics","marks":"65"}]},{"name":"PQR","subject":[{"name":"Chemistry","marks":"53"},{"name":"Biology","marks":"22"},{"name":"English","marks":"7 "},{"name":"Math","marks":"12"}]},{"name":"JKL","subject":[{"name":"Chemistry","marks":"53"},{"name":"Biology","marks":"22"},{"name":"English","marks":"79 "},{"name":"Math","marks":"12"},{"name":"Physics","marks":"72"}]}]';
final studentMarks = studentMarksFromJson(jsonString);
var subjects = <Subject?>{};
var subjectsDist = <Subject?>{};
int c=0;
for (var stdnt in studentMarks) {
for (var subjs in stdnt.subject) {
if (!subjectsDist.where((element) => element?.name==subjs.name).isNotEmpty) {
subjs.sno=c++;
subjectsDist.add(subjs);
}
}
}
print(subjectsDist.length);
List<List<OrdinalMarks>> SubjectData = [];
for (var subjs in subjectsDist) {
List<OrdinalMarks> marksData = [];
for (var stdnt in studentMarks) {
if (stdnt.subject
.where((element) => element.name == subjs?.name).isNotEmpty) {
var temp = stdnt.subject
.where((element) => element.name == subjs?.name)
.first;
marksData.add(OrdinalMarks(temp.name, int.parse(temp.marks),stdnt.name));
} else {
marksData.add(OrdinalMarks(subjs!.name, 0,stdnt.name));
}
}
SubjectData.add(marksData);
}
var palettes = charts.MaterialPalette.getOrderedPalettes(subjectsDist.length+2);
int cnt=0;
List<charts.Series<OrdinalMarks, String>> chartData = [
];
for(var d in SubjectData)
{
chartData.add(new charts.Series<OrdinalMarks, String>(
id: d.first.subjectName,
domainFn: (OrdinalMarks m, _) => m.studentName,
measureFn: (OrdinalMarks m, _) => m.marks,
data: d,
fillColorFn: ( subj, _) {
// print(subj.subjectName+": subj.subjectName :" + pallets[subj.subjectName].toString()??charts.MaterialPalette.blue.shadeDefault.toString());
return palettes.elementAt( subjectsDist.where((element) => element?.name==subj.subjectName).first?.sno??0 ).shadeDefault; //pallets[subj.subjectName]??charts.MaterialPalette.blue.shadeDefault;
},
colorFn: ( subj, _) {
// print(subj.subjectName+": subj.subjectName :" + pallets[subj.subjectName].toString()??charts.MaterialPalette.blue.shadeDefault.toString());
return palettes.elementAt(subjectsDist.where((element) => element?.name==subj.subjectName).first?.sno??0).shadeDefault;
},
));
}
return Scaffold(
// Use Obx(()=> to update Text() whenever count is changed.
appBar: AppBar(title: Text("Chart")),
// Replace the 8 lines Navigator.push by a simple Get.to(). You don't need context
body:new charts.BarChart(
chartData,
animate: animate,
behaviors: [new charts.SeriesLegend(showMeasures: true)],
animationDuration: Duration(seconds: 3),
));
}
}
/// Sample ordinal data type.
class OrdinalMarks {
final String subjectName;
final int marks;
final String studentName;
OrdinalMarks(this.subjectName, this.marks,this.studentName);
}
List<StudentMarks> studentMarksFromJson(String str) => List<StudentMarks>.from(json.decode(str).map((x) => StudentMarks.fromJson(x)));
String studentMarksToJson(List<StudentMarks> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class StudentMarks {
StudentMarks({
required this.name,
required this.subject,
});
String name;
List<Subject> subject;
factory StudentMarks.fromJson(Map<String, dynamic> json) => StudentMarks(
name: json["name"],
subject: List<Subject>.from(json["subject"].map((x) => Subject.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"name": name,
"subject": List<dynamic>.from(subject.map((x) => x.toJson())),
};
}
class Subject {
Subject({
required this.name,
required this.marks,
});
String name;
String marks;
int? sno;
factory Subject.fromJson(Map<String, dynamic> json) => Subject(
name: json["name"],
marks: json["marks"],
);
Map<String, dynamic> toJson() => {
"name": name,
"marks": marks,
};
}

type 'String' is not a subtype of type 'int' of 'index' while getting media fields using the instagram API

i'm trying to get media fields from the instagram api and i'm getting this error
type 'String' is not a subtype of type 'int' of 'index'
here's Homepage.dart :
import 'package:flutter/material.dart';
import 'package:get_storage/get_storage.dart';
import 'package:insta_details/models/data.dart';
import 'package:insta_details/utils/custom_dio_mixin.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
static String id = "HomePage";
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with CustomDioMixin {
bool loading = true;
bool error = false;
late Media media;
#override
void initState() {
super.initState();
getData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: loading
? const Center(
child: CircularProgressIndicator(),
)
: error
? const Center(
child: Text('An error has occurred!'),
)
: ListView.builder(
itemBuilder: (context, index) => MediaWidget(
media: media,
),
),
),
);
}
Future<void> getData() async {
try {
final storage = GetStorage();
final token = storage.read("accessToken");
Media? media;
final response = await dio.get(
'https://graph.instagram.com/me/media?fields=id,caption,media_url,timestamp&access_token=$token',
);
print("get data response => ${response.statusCode} ${response.data}");
Media mediadata = Media.fromJson(response.data);
print(mediadata);
} catch (e) {
print("get data failed");
print(e);
setState(() {
error = true;
});
} finally {
setState(() {
loading = false;
});
}
}
}
class MediaWidget extends StatelessWidget {
final Media media;
const MediaWidget({Key? key, required this.media}) : super(key: key);
#override
Widget build(BuildContext context) {
return GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemCount: 6,
itemBuilder: (context, index) {
return Image.network(media.mediaUrl);
},
);
}
}
and here data.dart :
class Media {
Media({
required this.id,
required this.caption,
required this.mediaUrl,
required this.timestamp,
});
String id;
String caption;
String mediaUrl;
String timestamp;
factory Media.fromJson(Map<String, dynamic> json) => Media(
id: json["data"]["id"] as String,
caption: json["data"]["caption"] as String,
mediaUrl: json["data"]["media_url"] as String,
timestamp: json["data"]["timestamp"] as String,
);
Map<String, dynamic> toJson() => {
"id": id,
"caption": caption,
"media_url": mediaUrl,
"timestamp": timestamp,
};
}
and the log :
I/flutter ( 5699): get data response => 200 {data: [{id: 18106429915287733, caption: cabin in the woods, media_url: https://scontent.cdninstagram.com/v/t51.29350-15/272751472_358111429123560_6575694365508668882_n.jpg?_nc_cat=100&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=0omRv4cUGtwAX8bbmC7&_nc_ht=scontent.cdninstagram.com&edm=ANo9K5cEAAAA&oh=00_AT_fqBkL5ykJXWRj7Rcy4nCnyuXEKh-8o0TX9FJkJ4dcfQ&oe=61FD881A, timestamp: 2022-01-27T11:15:07+0000}, {id: 17917394609104775, caption: Truck, media_url: https://scontent.cdninstagram.com/v/t51.29350-15/272701475_1080001635904581_1705933746471766077_n.jpg?_nc_cat=107&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=ZfSpeg7rHn4AX89PW0c&_nc_ht=scontent.cdninstagram.com&edm=ANo9K5cEAAAA&oh=00_AT_Qbj7zOH-UEzplA9mdIrCHaeb9EBBuz1RjKJclN9Q2RA&oe=61FE9898, timestamp: 2022-01-27T11:14:26+0000}, {id: 17921627228176014, caption: Gaara, media_url: https://scontent.cdninstagram.com/v/t51.29350-15/272660463_892749041374464_5507853711157520506_n.jpg?_nc_cat=101&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=va5seINOs-4AX9vOy4L&_nc_ht=scontent.cdninst
I/flutter ( 5699): get data failed
I/flutter ( 5699): type 'String' is not a subtype of type 'int' of 'index'
my JSON response :
{
"data": [
{
"id": "18106429915287733",
"caption": "cabin in the woods",
"media_type": "IMAGE",
"media_url": "https://scontent-iad3-1.cdninstagram.com/v/t51.29350-15/272751472_358111429123560_6575694365508668882_n.jpg?_nc_cat=100&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=xXGDvxMsycAAX_U_-55&_nc_ht=scontent-iad3-1.cdninstagram.com&edm=ANo9K5cEAAAA&oh=00_AT-EuNnLxrBSNirBOl1prRXlHepdhQqUjYRBEv3Zh_Ld6Q&oe=61FD881A",
"username": "parekchampl",
"timestamp": "2022-01-27T11:15:07+0000"
},
{
"id": "17917394609104775",
"caption": "Truck",
"media_type": "IMAGE",
"media_url": "https://scontent-iad3-1.cdninstagram.com/v/t51.29350-15/272701475_1080001635904581_1705933746471766077_n.jpg?_nc_cat=107&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=ZfSpeg7rHn4AX_J_eQs&_nc_ht=scontent-iad3-1.cdninstagram.com&edm=ANo9K5cEAAAA&oh=00_AT92hbhb0XK56kxC-_e8kpM6QFLazDH0TDCfdIdEIpNinw&oe=61FC9E58",
"username": "parekchampl",
"timestamp": "2022-01-27T11:14:26+0000"
},
{
"id": "17921627228176014",
"caption": "Gaara",
"media_type": "IMAGE",
"media_url": "https://scontent-iad3-1.cdninstagram.com/v/t51.29350-15/272660463_892749041374464_5507853711157520506_n.jpg?_nc_cat=101&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=va5seINOs-4AX_SB6jL&_nc_ht=scontent-iad3-1.cdninstagram.com&edm=ANo9K5cEAAAA&oh=00_AT8rviJ6wbaT0yF1Hq2VprtnQ-W0rARS5oxIr52MIhC0Rw&oe=61FD720B",
"username": "parekchampl",
"timestamp": "2022-01-27T11:13:42+0000"
},
{
"id": "18024346318348836",
"caption": "Marceline",
"media_type": "IMAGE",
"media_url": "https://scontent-iad3-1.cdninstagram.com/v/t51.29350-15/272807293_686124672409566_4991399943515126026_n.jpg?_nc_cat=106&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=JMfTMSD_1c8AX-m5WDx&_nc_ht=scontent-iad3-1.cdninstagram.com&edm=ANo9K5cEAAAA&oh=00_AT_P38eDVtcqEYL053wGPkLjhHStLCh7_fgFnCg4LcH1yA&oe=61FD1F82",
"username": "parekchampl",
"timestamp": "2022-01-27T11:13:02+0000"
},
{
"id": "17859174368680579",
"caption": "uchiha shisui",
"media_type": "IMAGE",
"media_url": "https://scontent-iad3-1.cdninstagram.com/v/t51.29350-15/272721151_749467822692662_5191995429373550055_n.jpg?_nc_cat=111&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=01A68vtgY-kAX-ux6iB&_nc_ht=scontent-iad3-1.cdninstagram.com&edm=ANo9K5cEAAAA&oh=00_AT9oWtK9VWV8j3c8Ij2YXctIpuh9sC-NJO1BLCwFObDDSA&oe=61FE0B03",
"username": "parekchampl",
"timestamp": "2022-01-27T11:12:35+0000"
},
{
"id": "17917757036265369",
"caption": "Son and Father",
"media_type": "IMAGE",
"media_url": "https://scontent-iad3-1.cdninstagram.com/v/t51.29350-15/272660947_1107548556714461_1575953024252145708_n.jpg?_nc_cat=100&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=Mzj5Wp9sv_oAX_2Z4Nv&_nc_ht=scontent-iad3-1.cdninstagram.com&edm=ANo9K5cEAAAA&oh=00_AT8Ywp3DUIemrIoCPajFvivfTG_-AWvEs2fpkngYXUN6Lg&oe=61FE17A1",
"username": "parekchampl",
"timestamp": "2022-01-27T11:11:47+0000"
}
],
"paging": {
"cursors": {
"before": "QVFIUnpEcERJTXdYRjd3SVp3MUo2U25UeWhhdlgxQ2xMY0diR2pYVFhCVl9TUUhlM1hqYllKWUpEWXJtYW5RWW41am1Lc3B4U281TU14ZAFoxSVBkMVRsZAkZAB",
"after": "QVFIUkgtUzExdDNsYzgwUFhGdnRXQlB6N0JkZATVFeU1DVkhzXzduLTF1RklpR1A5MDNMeWVEemtzdE15OVBlYmpYb29mQlVtdDJsX1N2SUcwa2ZAkc21jblZAn"
}
}
}
According to the documentation : https://developers.facebook.com/docs/instagram-basic-display-api/reference/media ,every field is a String
factory Media.fromJson(Map<String, dynamic> json) => Media(
id: json["data"]["id"] as String,
caption: json["data"]["caption"] as String,
mediaUrl: json["data"]["media_url"] as String,
timestamp: json["data"]["timestamp"] as String,
);
Or change to something like below:
factory Media.fromJson(Map<String, dynamic> json) => Media(
id: int.parse(json["data"]["id"] as String),
caption: json["data"]["caption"] as String,
mediaUrl: json["data"]["media_url"] as String,
timestamp: DateTime.parse(json["data"]["timestamp"] as String),
);
The value of your data key is a List not a Map. Here's an example:
const responseData =
{
"data":[
{
"id":"18106429915287733",
"caption":"cabin in the woods",
"media_type":"IMAGE",
"media_url":"https://scontent-iad3-1.cdninstagram.com/v/t51.29350-15/272751472_358111429123560_6575694365508668882_n.jpg?_nc_cat=100&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=xXGDvxMsycAAX_U_-55&_nc_ht=scontent-iad3-1.cdninstagram.com&edm=ANo9K5cEAAAA&oh=00_AT-EuNnLxrBSNirBOl1prRXlHepdhQqUjYRBEv3Zh_Ld6Q&oe=61FD881A",
"username":"parekchampl",
"timestamp":"2022-01-27T11:15:07+0000"
},
{
"id":"17917394609104775",
"caption":"Truck",
"media_type":"IMAGE",
"media_url":"https://scontent-iad3-1.cdninstagram.com/v/t51.29350-15/272701475_1080001635904581_1705933746471766077_n.jpg?_nc_cat=107&ccb=1-5&_nc_sid=8ae9d6&_nc_ohc=ZfSpeg7rHn4AX_J_eQs&_nc_ht=scontent-iad3-1.cdninstagram.com&edm=ANo9K5cEAAAA&oh=00_AT92hbhb0XK56kxC-_e8kpM6QFLazDH0TDCfdIdEIpNinw&oe=61FC9E58",
"username":"parekchampl",
"timestamp":"2022-01-27T11:14:26+0000"
}
]
};
void main() {
final mediaList = responseData["data"]!.map((entry) => Media.fromJson(entry))
.toList();
for (var media in mediaList) {
print(media.id);
}
}
class Media {
Media({
required this.id,
required this.caption,
required this.mediaUrl,
required this.timestamp,
});
int? id;
String caption;
String mediaUrl;
String timestamp;
factory Media.fromJson(Map<String, dynamic> json) {
return Media(
id: int.tryParse(json["id"]),
caption: json["caption"],
mediaUrl: json["media_url"],
timestamp: json["timestamp"],
);
}
Map<String, dynamic> toJson() => {
"id": id.toString(),
"caption": caption,
"media_url": mediaUrl,
"timestamp": timestamp,
};
}
On your model class id is nullable int, but you are receiving id as String.
You can typecast string to int On your Media.fromJson, while the id accept null value, if something wrong happen id will get null value.
factory Media.fromJson(Map<String, dynamic> json) => Media(
id: int.tryParse(json["data"]["id"]),
And for toJson pass id as String
Map<String, dynamic> toJson() => {
"id": id.toString(),
More about int.tryParse.

Flutter - Parse multiple json array and set to list

HERE IS THE JSON OF RESPONSE BODY:
{
"status": "success",
"contents": [{
"id": "15",
"cname": "DOGS",
"dogs_image": "1638695967-rtyyyt.jpg",
"cat_image": "1638695967-jhjjj.jpg",
"sub_category": [{
"subcatid": "36",
"cat_id": "15",
"sub_category_name": "Accessories",
"banner": null,
"image": "1638695982-ACCESORIE.jpg"
}, {
"subcatid": "39",
"cat_id": "15",
"sub_category_name": "Beds",
"banner": null,
"image": "1638695982-ACCESORIE.jpg"
}]
}, {
"id": "14",
"cname": "CATS",
"dogs_image": "1638695967-rtyyyt.jpg",
"cat_image": "1638695967-jhjjj.jpg",
"sub_category": [{
"subcatid": "47",
"cat_id": "14",
"sub_category_name": "Accessories",
"banner": null,
"image": "1638695982-ACCESORIE.jpg"
}]
}]
}
// API call to get the above json data:
Future<List<CatListData>> dashboardDataAPI(http.Client client) async {
final response = await client.get(Uri.parse(Utilities.BASE_URL));
List list = json.decode(response.body)['contents'];
return parsePhotos(list.toString());
}
// A function that converts a response body into a List
List<CatListData> parsePhotos(String responseBody) {
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<CatListData>((json) => CatListData.fromJson(json)).toList();
}
// Cat List Class
class CatListData{
final String id;
final String cName;
final String dogImage;
final String catImage;
final List<SubCatListData> subCatListDataList;
CatListData({required this.id, required this.cName, required this.dogImage, required this.catImage, required this.subCatListDataList});
factory CatListData.fromJson(Map<String, dynamic> json) {
return CatListData(
id: json['id'] as String,
cName: json['cname'] as String,
dogImage: json['dogs_image'] as String,
catImage: json['cat_image'] as String,
subCatListDataList: List<SubCatListData>.from(json['sub_category'] as Iterable),
);
}
}
// Sub Cat Class
class SubCatListData{
final String subCatId;
final String catId;
final String subCategoryName;
final String banner;
final String image;
SubCatListData({required this.subCatId, required this.catId, required this.subCategoryName, required this.banner, required this.image});
factory SubCatListData.fromJson(Map<String, dynamic> json) {
return SubCatListData(
subCatId: json['subcatid'] as String,
catId: json['cat_id'] as String,
subCategoryName: json['sub_category_name'] as String,
banner: json['banner'] as String,
image: json['image'] as String,
);
}
}
Here showing null when I print snapshot
Container(
child: FutureBuilder<List<CatListData>>(
future: dashboardDataAPI(http.Client()),
builder: (context, snapshot) {
print("Response:: "+snapshot.data.toString());
if (snapshot.hasData) {
return PhotosList(photos: snapshot.data!);
}else if(snapshot.hasError){
return const Center(
child: Text('An error has occurred!'),);
}else{
return const Center(
child: CircularProgressIndicator(),
);
}
},
),
)
Please let me know how I can fix this issue and parse the multiple json array data into the list.
Thanks
I believe the problem happens on this line on the CatListData.fromJson constructor:
subCatListDataList: List<SubCatListData>.from(json['sub_category'] as Iterable),
you never call SubCatListData.fromJson, I believe this will work better for your assignment:
subCatListDataList: (json['sub_category'] as Iterable).map<SubCatListData>(
(value) => SubCatListData.fromJson(value as Map<String, dynamic>),
),