Mapping response.body to model class - json

I'm trying to map response to model class and then show all elements one by one, so that user can scroll down. Response goes like that:
{"items":[{"id":"bd9acd37-5c91-47cb-a71e-0e43fb2f7882","imageUrl":"","title":"fak hez as","city":"Gdansk"},{"id":"210ad8c8-d279-4c38-845c-34c772cfec21","imageUrl":"","title":"Some random title :)","city":"Warsaw"}],"total":2,"pageNumber":1}
And my model which I have generated with https://plugins.jetbrains.com/plugin/12562-jsontodart-json-to-dart-
class Advertisement {
List<Items>? _items;
int? _total;
int? _pageNumber;
List<Items>? get items => _items;
int? get total => _total;
int? get pageNumber => _pageNumber;
Advertisement({List<Items>? items, int? total, int? pageNumber}) {
_items = items;
_total = total;
_pageNumber = pageNumber;
}
Advertisement.fromJson(dynamic json) {
if (json["items"] != null) {
_items = [];
json["items"].forEach((v) {
_items?.add(Items.fromJson(v));
});
}
_total = json["total"];
_pageNumber = json["pageNumber"];
}
Map<String, dynamic> toJson() {
var map = <String, dynamic>{};
if (_items != null) {
map["items"] = _items?.map((v) => v.toJson()).toList();
}
map["total"] = _total;
map["pageNumber"] = _pageNumber;
return map;
}
}
/// id : "bd9acd37-5c91-47cb-a71e-0e43fb2f7882"
/// imageUrl : ""
/// title : "fak hez as"
/// city : "Gdansk"
class Items {
String? _id;
String? _imageUrl;
String? _title;
String? _city;
String? get id => _id;
String? get imageUrl => _imageUrl;
String? get title => _title;
String? get city => _city;
Items({String? id, String? imageUrl, String? title, String? city}) {
_id = id;
_imageUrl = imageUrl;
_title = title;
_city = city;
}
Items.fromJson(dynamic json) {
_id = json["id"];
_imageUrl = json["imageUrl"];
_title = json["title"];
_city = json["city"];
}
Map<String, dynamic> toJson() {
var map = <String, dynamic>{};
map["id"] = _id;
map["imageUrl"] = _imageUrl;
map["title"] = _title;
map["city"] = _city;
return map;
}
}
My screen:
import 'dart:convert';
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:.../constants/AppConstants.dart';
import 'package:.../ui/pages/home/page/Advertisement.dart';
import 'package:.../util/HttpActions.dart';
import 'BottomAppBar.dart';
import 'FAB.dart';
import 'Advertisement.dart';
class HomePage extends StatefulWidget {
final String jwt;
const HomePage(this.jwt);
#override
_HomePage createState() => _HomePage();
factory HomePage.fromBase64(String jwt) => HomePage(jwt);
}
class _HomePage extends State<HomePage> {
late final String jwt;
#override
void initState() {
super.initState();
jwt = widget.jwt;
}
#override
Widget build(BuildContext context) => Scaffold(
body: Scaffold(
backgroundColor: const Color(0xFEF9F9FC),
floatingActionButtonLocation:
FloatingActionButtonLocation.centerDocked,
floatingActionButton: buildFAB(),
bottomNavigationBar: BuildBottomAppBar(),
body: Container(
padding: EdgeInsets.all(35.0),
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Column(
children: [
FutureBuilder(
future: fetchAdvertisements(),
builder: (context, snapshot) => snapshot.hasData
? Text("")
: snapshot.hasError
? Text("An error occurred")
: CircularProgressIndicator(),
),
],
),
),
),
);
Future<List<Advertisement>?> fetchAdvertisements() async {
var response = await HttpActions.makeHttpGet(
{},
AppConstants.ADVERTISEMENTS_ENDPOINT,
{HttpHeaders.contentTypeHeader: HttpActions.APPLICATION_JSON_HEADER});
print(response.statusCode);
if (response.statusCode == 200) {
print(response.body);
final responseList = json.decode(response.body);
print(responseList);
List<Advertisement> z = (json.decode(response.body) as List)
.map((i) => Advertisement.fromJson(i))
.toList();
print(z);
return null;
} else {
throw Exception('Failed to load post');
}
}
}
Error occurs while executing this line:
List<Advertisement> z = (json.decode(response.body) as List)
.map((i) => Advertisement.fromJson(i))
.toList();
it does not map to this List
While debugging I get:
What I'm making wrong? Is there something wrong with model class?

One more mistake that you are making with your code, You are calling fetchAdvertisement() method inside a build(BuildContext context). This means everytime build() method gets called. It will call fetchAdvertisement() this as well.
Column(
children: [
FutureBuilder(
future: fetchAdvertisements(),
builder: (context, snapshot) => snapshot.hasData
? Text("")
: snapshot.hasError
? Text("An error occurred")
: CircularProgressIndicator(),
),
],
),
To avoid such an issue.
late Function _fetchAdvertisements;
void initState() {
super.initState();
_fetchAdvertisements = fetchAdvertisements(); }
Column(
children: [
FutureBuilder(
future: _fetchAdvertisements,
builder: (context, snapshot) => snapshot.hasData
? Text("")
: snapshot.hasError
? Text("An error occurred")
: CircularProgressIndicator(),
),
],
),

You cannot simply parse this with cast as List. Because your response isn't even a List.
{
"items": [
{
"id": "bd9acd37-5c91-47cb-a71e-0e43fb2f7882",
"imageUrl": "",
"title": "fak hez as",
"city": "Gdansk"
},
{
"id": "210ad8c8-d279-4c38-845c-34c772cfec21",
"imageUrl": "",
"title": "Pozdrawiam z Łodzi :)",
"city": "Warsaw"
}
],
"total": 2,
"pageNumber": 1
}
For this response, you can parse this like this:
Advertisement.fromJson(json.decode(response.body))
But now you have only one item of Advertisement.
If your response were like this, with multiple advertisements:
{
"advertisements": [
{
"items": [
{
"id": "bd9acd37-5c91-47cb-a71e-0e43fb2f7882",
"imageUrl": "",
"title": "fak hez as",
"city": "Gdansk"
},
{
"id": "212ad8c8-d279-4c38-845c-34c772cfec21",
"imageUrl": "",
"title": "Great city!",
"city": "Łódź"
}
],
"total": 2,
"pageNumber": 1
},
{
"items": [
{
"id": "bd9acd37-5c91-47cb-a71e-0e43fb2f7882",
"imageUrl": "",
"title": "fak hez as",
"city": "Gdansk"
},
{
"id": "210ad8c8-d279-4c38-845c-34c772cfec21",
"imageUrl": "",
"title": "Some random title :)",
"city": "Warsaw"
}
],
"total": 2,
"pageNumber": 1
}
]
}
You can parse this simply with this code:
List<Advertisement> advertisements = [
for (final advertisement in json.decode(response2)['advertisements'])
Advertisement.fromJson(advertisement)
];
You can learn how to do JSON serialization properly with JsonSerializable I recommend you to read this here.

I just copied you responded.body text and showed you a dummy example. Everything will be done in the same way, weather you use an HTTP calls. Always make sure that you know what response is coming.
class __AppState extends State<_App> {
#override
void initState() {
// TODO: implement initState
super.initState();
convertApiResponse();
}
Future<String> getApiJson() async {
return '{"items":[{"id":"bd9acd37-5c91-47cb-a71e-0e43fb2f7882","imageUrl":"","title":"fak hez as","city":"Gdansk"},{"id":"210ad8c8-d279-4c38-845c-34c772cfec21","imageUrl":"","title":"Some random title :)","city":"Warsaw"}],"total":2,"pageNumber":1} ';
}
Future<void> convertApiResponse() async {
final data = await getApiJson();
final decodedData = json.decode(data) as Map;
Advertisement x = Advertisement.fromJson(decodedData);
x._items!.forEach((element) {
log("Item-> City: ${element.city}");
log("Item->ID: ${element.id}");
log("Item->ImageURL: ${element.imageUrl}");
log("Item->Title: ${element.title}");
});
log("Page Number: ${x.pageNumber}");
log("Total: ${x.total}");
}
#override
Widget build(BuildContext context) {
return MaterialApp(home: Scaffold());
}
}
Untouched Items.dart
class Items {
String? _id;
String? _imageUrl;
String? _title;
String? _city;
String? get id => _id;
String? get imageUrl => _imageUrl;
String? get title => _title;
String? get city => _city;
Items({String? id, String? imageUrl, String? title, String? city}) {
_id = id;
_imageUrl = imageUrl;
_title = title;
_city = city;
}
Items.fromJson(dynamic json) {
_id = json["id"];
_imageUrl = json["imageUrl"];
_title = json["title"];
_city = json["city"];
}
Map<String, dynamic> toJson() {
var map = <String, dynamic>{};
map["id"] = _id;
map["imageUrl"] = _imageUrl;
map["title"] = _title;
map["city"] = _city;
return map;
}
}
Untouched Advertisement.dart
class Advertisement {
List<Items>? _items;
int? _total;
int? _pageNumber;
List<Items>? get items => _items;
int? get total => _total;
int? get pageNumber => _pageNumber;
Advertisement({List<Items>? items, int? total, int? pageNumber}) {
_items = items;
_total = total;
_pageNumber = pageNumber;
}
Advertisement.fromJson(dynamic json) {
if (json["items"] != null) {
_items = [];
json["items"].forEach((v) {
_items?.add(Items.fromJson(v));
});
}
_total = json["total"];
_pageNumber = json["pageNumber"];
}
Map<String, dynamic> toJson() {
var map = <String, dynamic>{};
if (_items != null) {
map["items"] = _items?.map((v) => v.toJson()).toList();
}
map["total"] = _total;
map["pageNumber"] = _pageNumber;
return map;
}
}

Here is a picture that resolves your fetchAdvertisements() call on every build

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();
},
);
}
}

showing key along side data json

Hi I have a dynamic json the details in it changes in every product so I wanna show keys along side their corresponding data
any example would be great I am struggling with this. sample json in appDetails wanna show all the keys like systemoverview,benefits, mainFeatures and their data.
In next product it will be changed but appdetails will remain same.
import 'package:flutter/material.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MaterialApp(home: TestScreen()));
}
class TestScreen extends StatefulWidget {
const TestScreen({Key? key}) : super(key: key);
#override
State<TestScreen> createState() => _TestScreenState();
}
class _TestScreenState extends State<TestScreen> {
List<AppDetails>? details = [];
final Map<String, dynamic> json = {
"name": "TestingApp",
"category": "Production",
"subcategory": "Productivity",
"imageUrl": "Testing-Banner.jpg",
"logo": "PI.png",
"description": "Testing is an application for easy & effective Inspection",
"appDetails": [
{
"systemOverview": "https:url.com",
"multiDeviceSupport": [
{"item1": "Multi-Device"},
{"item2": "Multi-Lingual"},
{"item3": "Multi-Database"}
],
"mainFeatures": [
{"feature1": "Testing"},
{"feature2": "Ease"},
{"feature3": "Select failure "}
],
"benefits": [
{"benfits1": "Easy & quick solution "},
{"benefits2": "Go paperless "},
personnel’s"}
]
}
]
};
#override
void initState() {
super.initState();
final data = AppDetailModel.fromJson(json);
details = data.appDetails;
List<AppDetails>? parseCategorizedBooksJson(Map<String, dynamic> json) => [
for (var detai in json.values)
for (var de in detai) AppDetails.fromJson(de)
];
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.blue,
title: const Text('Home'),
),
body: SizedBox(
child: ListView.builder(
itemCount: details?.length,
itemBuilder: (context, index) {
final detail = details?[index];
return buildProduct(detail);
},
),
),
);
}
}
Widget buildProduct(AppDetails? detail) => Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: (detail?.benefits ?? []).map((e) {
final index = (detail?.benefits ?? []).indexOf(e);
return Row(
children: [
SizedBox(width: 20, child: Text('${index + 1}.')),
Text('${e.label}'),
],
);
}).toList(),
),
);
class AppDetailModel {
String? name;
String? category;
String? subcategory;
String? imageUrl;
String? logo;
String? description;
List<AppDetails>? appDetails;
AppDetailModel(
{this.name,
this.category,
this.subcategory,
this.imageUrl,
this.logo,
this.description,
this.appDetails});
AppDetailModel.fromJson(Map<String, dynamic> json) {
name = json['name'];
category = json['category'];
subcategory = json['subcategory'];
imageUrl = json['imageUrl'];
logo = json['logo'];
description = json['description'];
if (json['appDetails'] != null) {
appDetails = <AppDetails>[];
json['appDetails'].forEach((v) {
appDetails!.add(AppDetails.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['name'] = name;
data['category'] = category;
data['subcategory'] = subcategory;
data['imageUrl'] = imageUrl;
data['logo'] = logo;
data['description'] = description;
if (appDetails != null) {
data['appDetails'] = appDetails!.map((v) => v.toJson()).toList();
}
return data;
}
}
class AppDetails {
String? systemOverview;
List<Label>? multiDeviceSupport;
List<Label>? mainFeatures;
List<Label>? benefits;
AppDetails(
{this.systemOverview,
this.multiDeviceSupport,
this.mainFeatures,
this.benefits});
AppDetails.fromJson(Map<String, dynamic> json) {
systemOverview = json['systemOverview'];
if (json['multiDeviceSupport'] != null) {
multiDeviceSupport = <Label>[];
json['multiDeviceSupport'].forEach((v) {
multiDeviceSupport!.add(Label.fromJson(v));
});
}
if (json['mainFeatures'] != null) {
mainFeatures = <Label>[];
json['mainFeatures'].forEach((v) {
mainFeatures!.add(Label.fromJson(v));
});
}
if (json['benefits'] != null) {
benefits = <Label>[];
json['benefits'].forEach((v) {
benefits!.add(Label.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['systemOverview'] = systemOverview;
if (multiDeviceSupport != null) {
data['multiDeviceSupport'] =
multiDeviceSupport!.map((v) => v.toJson()).toList();
}
if (mainFeatures != null) {
data['mainFeatures'] = mainFeatures!.map((v) => v.toJson()).toList();
}
if (benefits != null) {
data['benefits'] = benefits!.map((v) => v.toJson()).toList();
}
return data;
}
}
class Label {
String? label;
Label({this.label});
Label.fromJson(Map<String, dynamic> json) {
label = json['label'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['label'] = label;
return data;
}
}
```
currently What I am doing right now
so taking your example:
final map = {
"appDetails": [
{
"systemOverview": "https:url.com",
"multiDeviceSupport": [
{"label": "Multi-Device"}
],
"mainFeatures": [
{"label": "Testing"}
],
"benefits": [
{"label": "Easy & quick solution "},
{"label": "Go paperless "}
]
}
]
};
we can get both the key and value using the entries like this:
map!["appDetails"]![0].entries.forEach((e) {
print("${e.key}, ${e.value}");
});
This code will print this result:
systemOverview, https:url.com
multiDeviceSupport, [{label: Multi-Device}]
mainFeatures, [{label: Testing}]
benefits, [{label: Easy & quick solution }, {label: Go paperless }]
it will print the key along with it's value, you can use this sample to achieve your result.
print all keys of JSON data
var data = convert.jsonDecode(response.body);
print(data.keys.toList());
you can do somthing like this
Column(children:
data['appDetails']
.map(
(system) => Column(
children: system.entries
.map<Widget>(
(systemeEntry) => systemeEntry.value is String
? Row(
children: [
Text("${systemeEntry.key}: "),
Expanded(child: Text(systemeEntry.value)),
],
)
: systemeEntry.value is List
? Row(
children: [
Text(" ${systemeEntry.key} => "),
Expanded(
child: Column(
children:
systemeEntry.value is List
? systemeEntry.value
.map<Widget>(
(detail) => Column(
children: [
...detail
.entries
.map(
(detailEntry) =>
Row(
children: [
Text(" ${detailEntry.key}: "),
Text(detailEntry.value),
]),
)
.toList()
]),
)
.toList()
: [const SizedBox()],
),
)
],
)
: const SizedBox(),
)
.toList(),
),
)
.toList(),
)

Stuck with json in flutter

I dont know the problem is because when debuging there isn't error info but the value of json is empty when I print info.lenght
class _HomePageState extends State<HomePage> {
List info = [];
_initData(){
DefaultAssetBundle.of(context).loadString("json/info.json").then((value){
info = jsonDecode(value);
});
}
#override
void iniState(){
super.initState();
_initData();
}
and below is my json code in json/info.json
[
{
"title": "Glue",
"img": "assets/ex1.png"
},
{
"title": "Abs",
"img": "assets/ex2.png"
},
{
"title": "Legs",
"img": "assets/ex3.png"
},
{
"title": "Arms",
"img": "assets/ex4.png"
}
]
and how to we print the img and title value of json in dart?
You have to first create a model class for your json response.
// To parse this JSON data, do
//
// final jsonModel = jsonModelFromJson(jsonString);
import 'dart:convert';
List<JsonModel> jsonModelFromJson(String str) => List<JsonModel>.from(json.decode(str).map((x) => JsonModel.fromJson(x)));
String jsonModelToJson(List<JsonModel> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class JsonModel {
JsonModel({
this.title,
this.img,
});
String title;
String img;
factory JsonModel.fromJson(Map<String, dynamic> json) => JsonModel(
title: json["title"] == null ? null : json["title"],
img: json["img"] == null ? null : json["img"],
);
Map<String, dynamic> toJson() => {
"title": title == null ? null : title,
"img": img == null ? null : img,
};
}
then just use this model class to decode your json file.
var result = JsonModel.fromJson(jsonResponse);
Later, you can just use
result.title or result.img to get the data
You have to add your json file into pubspec.yaml file.
flutter:
assets:
- json/info.json
Before loading page view, you should load values from your json file and assign a list in initState. After that, you can use list as map by [index][header].
class JsonResult extends StatefulWidget {
const JsonResult({Key? key}) : super(key: key);
#override
_JsonResultState createState() => _JsonResultState();
}
class _JsonResultState extends State<JsonResult> {
var jsonList = [];
#override
void initState() {
rootBundle.loadString("json/info.json").then((value) {
jsonList = json.decode(value);
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ListView.builder(
itemBuilder: (context, index) {
return ListTile(
leading: Image.asset(jsonList[index]["img"]),
title: Text(jsonList[index]["title"]),
);
},
itemCount: jsonList.length,
),
),
);
}
}

How to parse in nested json array in ListView.Builder in Flutter

I'm calling an api which returns a nested json array list and when i try to display an id of table_photos inside listview.builder then it is displaying only id:1. I want to display all three id's which is id:1,id:11,id:12 inside listview.builder. Below is the sample json along with the code and MainPage.dart i'm displaying only short code due to the long file
JSON
{
"message": "Tables returend",
"tables": [
{
"id": "7"
"table_photos": [
{
"id": "7"
}
]
},
{
"id": "6",
"table_photos": [
{
"id": "1"
},
{
"id": "11"
},
{
"id": "12"
}
]
}
]
}
Model
class TableGenerateTablesTablePhotos {
String? id;
TableGenerateTablesTablePhotos({
this.id,
});
TableGenerateTablesTablePhotos.fromJson(Map<String, dynamic> json) {
id = json["id"]?.toString();
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>();
data["id"] = id;
return data;
}
}
class TableGenerateTables {
String? id;
List<TableGenerateTablesTablePhotos?>? tablePhotos;
TableGenerateTables({
this.id,
this.tablePhotos,
});
TableGenerateTables.fromJson(Map<String, dynamic> json) {
id = json["id"]?.toString();
if (json["table_photos"] != null) {
final v = json["table_photos"];
final arr0 = <TableGenerateTablesTablePhotos>[];
v.forEach((v) {
arr0.add(TableGenerateTablesTablePhotos.fromJson(v));
});
tablePhotos = arr0;
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>();
data["id"] = id;
if (tablePhotos != null) {
final v = tablePhotos;
final arr0 = [];
v!.forEach((v) {
arr0.add(v!.toJson());
});
data["table_photos"] = arr0;
}
return data;
}
}
class TableGenerate {
String? message;
List<TableGenerateTables?>? tables;
TableGenerate({
this.message,
this.tables,
});
TableGenerate.fromJson(Map<String, dynamic> json) {
message = json["message"]?.toString();
if (json["tables"] != null) {
final v = json["tables"];
final arr0 = <TableGenerateTables>[];
v.forEach((v) {
arr0.add(TableGenerateTables.fromJson(v));
});
tables = arr0;
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>();
data["message"] = message;
if (tables != null) {
final v = tables;
final arr0 = [];
v!.forEach((v) {
arr0.add(v!.toJson());
});
data["tables"] = arr0;
}
return data;
}
}
Repository
class Repository{
Future<List< TableGenerateTables >?> makeRequestTables(int id, int count) async {
var response = await http.get(
Uri.parse('API_URL'));
if (response.statusCode == 200) {
var data = jsonDecode(response.body);
List< TableGenerateTables >? tables =
TableGenerate.fromJson(data).tables as List< TableGenerateTables >;
return tables;
} else {
throw Exception();
}
}
}
MainPage.dart
Widget showTable(List<TablesTables> data) {
return ListView.builder(
shrinkWrap: true,
itemCount: data.length,
itemBuilder: (BuildContext context, int index) {
return Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(data[index].tablePhotos![index]!.id!), //It is displaying "1"
],
),
);
});
}

How to parse a complex Json value in flutter?

I have a JSON which is a combination of simple and complicated structures.Anyhow you can have a look at it.All I want is to get the "playlist_url": value and display it a listview builder.Along with that I want to parse for 2 text values which I am able to do.But the url part is where I am not able to resolve
The JSON structure(it is too long,thats y I have given the link): https://docs.google.com/document/d/1saJN3MQvG55M1ipf42-65Etowi_kW80gkrosU6vBb5o/edit?usp=sharing
The PODO file:
// To parse this JSON data, do
//
// final homePage = homePageFromJson(jsonString);
import 'dart:convert';
HomePage homePageFromJson(String str) => HomePage.fromJson(json.decode(str));
String homePageToJson(HomePage data) => json.encode(data.toJson());
class HomePage {
HomePage({
this.series,
this.homeBanners,
this.liveChannels,
this.publishers,
this.musicCategories,
this.musicPlaylists,
this.movies,
});
List<HomeBanner> series;
List<HomeBanner> homeBanners;
List<LiveChannel> liveChannels;
List<Publisher> publishers;
List<Music> musicCategories;
Music musicPlaylists;
List<HomeBanner> movies;
factory HomePage.fromJson(Map<String, dynamic> json) => HomePage(
series: List<HomeBanner>.from(
json["series"].map((x) => HomeBanner.fromJson(x))),
homeBanners: List<HomeBanner>.from(
json["home_banners"].map((x) => HomeBanner.fromJson(x))),
liveChannels: List<LiveChannel>.from(
json["live_channels"].map((x) => LiveChannel.fromJson(x))),
publishers: List<Publisher>.from(
json["publishers"].map((x) => Publisher.fromJson(x))),
musicCategories: List<Music>.from(
json["music_categories"].map((x) => Music.fromJson(x))),
musicPlaylists: Music.fromJson(json["music_playlists"]),
movies: List<HomeBanner>.from(
json["movies"].map((x) => HomeBanner.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"series": List<dynamic>.from(series.map((x) => x.toJson())),
"home_banners": List<dynamic>.from(homeBanners.map((x) => x.toJson())),
"live_channels":
List<dynamic>.from(liveChannels.map((x) => x.toJson())),
"publishers": List<dynamic>.from(publishers.map((x) => x.toJson())),
"music_categories":
List<dynamic>.from(musicCategories.map((x) => x.toJson())),
"music_playlists": musicPlaylists.toJson(),
"movies": List<dynamic>.from(movies.map((x) => x.toJson())),
};
}
class HomeBanner {
HomeBanner({
this.movieId,
this.title,
this.tags,
this.genres,
this.thumbnail,
this.posterLink,
this.platform,
this.worldwide,
this.createdAt,
this.seriesId,
});
String movieId;
String title;
List<String> tags;
List<String> genres;
List<String> thumbnail;
String posterLink;
Platform platform;
double worldwide;
DateTime createdAt;
String seriesId;
factory HomeBanner.fromJson(Map<String, dynamic> json) => HomeBanner(
movieId: json["movie_id"] == null ? null : json["movie_id"],
title: json["title"],
tags: List<String>.from(json["tags"].map((x) => x)),
genres: List<String>.from(json["genres"].map((x) => x)),
thumbnail: List<String>.from(json["thumbnail"].map((x) => x)),
posterLink: json["poster_link"],
platform: platformValues.map[json["platform"]],
worldwide: json["WORLDWIDE"],
createdAt: DateTime.parse(json["createdAt"]),
seriesId: json["series_id"] == null ? null : json["series_id"],
);
Map<String, dynamic> toJson() => {
"movie_id": movieId == null ? null : movieId,
"title": title,
"tags": List<dynamic>.from(tags.map((x) => x)),
"genres": List<dynamic>.from(genres.map((x) => x)),
"thumbnail": List<dynamic>.from(thumbnail.map((x) => x)),
"poster_link": posterLink,
"platform": platformValues.reverse[platform],
"WORLDWIDE": worldwide,
"createdAt": createdAt.toIso8601String(),
"series_id": seriesId == null ? null : seriesId,
};
}
enum Platform { YOUTUBE, DISCOVERYPLUS }
final platformValues = EnumValues(
{"discoveryplus": Platform.DISCOVERYPLUS, "youtube": Platform.YOUTUBE});
class LiveChannel {
LiveChannel({
this.keyId,
this.postContent,
this.publisherId,
this.publisherName,
this.publisherProfilePic,
this.publisherDesc,
this.downvotesCount,
this.upvotesCount,
});
String keyId;
PostContent postContent;
String publisherId;
String publisherName;
String publisherProfilePic;
String publisherDesc;
int downvotesCount;
int upvotesCount;
factory LiveChannel.fromJson(Map<String, dynamic> json) => LiveChannel(
keyId: json["key_id"],
postContent: PostContent.fromJson(json["post_content"]),
publisherId: json["publisher_id"],
publisherName: json["publisher_name"],
publisherProfilePic: json["publisher_profile_pic"],
publisherDesc: json["publisher_desc"],
downvotesCount: json["downvotes_count"],
upvotesCount: json["upvotes_count"],
);
Map<String, dynamic> toJson() => {
"key_id": keyId,
"post_content": postContent.toJson(),
"publisher_id": publisherId,
"publisher_name": publisherName,
"publisher_profile_pic": publisherProfilePic,
"publisher_desc": publisherDesc,
"downvotes_count": downvotesCount,
"upvotes_count": upvotesCount,
};
}
class PostContent {
PostContent({
this.shortcode,
this.platformVideoLink,
this.caption,
this.description,
});
String shortcode;
String platformVideoLink;
String caption;
String description;
factory PostContent.fromJson(Map<String, dynamic> json) => PostContent(
shortcode: json["shortcode"],
platformVideoLink: json["platform_videoLink"],
caption: json["caption"],
description: json["description"],
);
Map<String, dynamic> toJson() => {
"shortcode": shortcode,
"platform_videoLink": platformVideoLink,
"caption": caption,
"description": description,
};
}
class Music {
Music({
this.id,
this.country,
this.categoryId,
this.categoryName,
this.categoryIcons,
this.playlists,
});
dynamic id;
String country;
String categoryId;
String categoryName;
List<CategoryIcon> categoryIcons;
List<Playlist> playlists;
factory Music.fromJson(Map<String, dynamic> json) => Music(
id: json["_id"],
country: json["country"],
categoryId: json["category_id"],
categoryName: json["category_name"],
categoryIcons: List<CategoryIcon>.from(
json["category_icons"].map((x) => CategoryIcon.fromJson(x))),
playlists: List<Playlist>.from(
json["playlists"].map((x) => Playlist.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"_id": id,
"country": country,
"category_id": categoryId,
"category_name": categoryName,
"category_icons":
List<dynamic>.from(categoryIcons.map((x) => x.toJson())),
"playlists": List<dynamic>.from(playlists.map((x) => x.toJson())),
};
}
class CategoryIcon {
CategoryIcon({
this.height,
this.url,
this.width,
});
int height;
String url;
int width;
factory CategoryIcon.fromJson(Map<String, dynamic> json) => CategoryIcon(
height: json["height"] == null ? null : json["height"],
url: json["url"],
width: json["width"] == null ? null : json["width"],
);
Map<String, dynamic> toJson() => {
"height": height == null ? null : height,
"url": url,
"width": width == null ? null : width,
};
}
class Playlist {
Playlist({
this.playlistName,
this.playlistDescription,
this.playlistUrl,
this.playlistTotalTracks,
this.playlistImages,
this.playlistFollowers,
this.playlistId,
});
String playlistName;
String playlistDescription;
String playlistUrl;
int playlistTotalTracks;
List<CategoryIcon> playlistImages;
int playlistFollowers;
String playlistId;
factory Playlist.fromJson(Map<String, dynamic> json) => Playlist(
playlistName: json["playlist_name"],
playlistDescription: json["playlist_description"],
playlistUrl: json["playlist_url"],
playlistTotalTracks: json["playlist_total_tracks"],
playlistImages: List<CategoryIcon>.from(
json["playlist_images"].map((x) => CategoryIcon.fromJson(x))),
playlistFollowers: json["playlist_followers"],
playlistId: json["playlist_id"],
);
Map<String, dynamic> toJson() => {
"playlist_name": playlistName,
"playlist_description": playlistDescription,
"playlist_url": playlistUrl,
"playlist_total_tracks": playlistTotalTracks,
"playlist_images":
List<dynamic>.from(playlistImages.map((x) => x.toJson())),
"playlist_followers": playlistFollowers,
"playlist_id": playlistId,
};
}
class Publisher {
Publisher({
this.platform,
this.username,
this.fullName,
this.profilePicUrl,
this.content,
this.keyId,
});
Platform platform;
String username;
String fullName;
String profilePicUrl;
Content content;
String keyId;
factory Publisher.fromJson(Map<String, dynamic> json) => Publisher(
platform: platformValues.map[json["platform"]],
username: json["username"],
fullName: json["full_name"],
profilePicUrl: json["profile_pic_url"],
content: Content.fromJson(json["content"]),
keyId: json["key_id"],
);
Map<String, dynamic> toJson() => {
"platform": platformValues.reverse[platform],
"username": username,
"full_name": fullName,
"profile_pic_url": profilePicUrl,
"content": content.toJson(),
"key_id": keyId,
};
}
class Content {
Content({
this.description,
});
String description;
factory Content.fromJson(Map<String, dynamic> json) => Content(
description: json["description"],
);
Map<String, dynamic> toJson() => {
"description": description,
};
}
class EnumValues<T> {
Map<String, T> map;
Map<T, String> reverseMap;
EnumValues(this.map);
Map<T, String> get reverse {
if (reverseMap == null) {
reverseMap = map.map((k, v) => new MapEntry(v, k));
}
return reverseMap;
}
}
The class called services where I am trying to parse the playlist_url.I am able to parse the playlist name and the number of videos of it(the count of it)
class Services {
static const String url =
"https://livetvapi.apyhi.com/api/v2/home?pageLocation=home&countries=IN&app_version=13&"
"user_id=44edc2c905ae163f&package_id=livetv.movies.freemovies.watchtv.tvshows&os_platform=android";
static Future<List<String>> loadDataForPlaylistDetailsForButtomTitle() async {
var res = await http
.get(url, headers: {'Authorization': dartJsonWebTokenGenerator()});
if (res.statusCode == 200) {
print("response is there");
final homePage = homePageFromJson(res.body);
Playlist playListObject = new Playlist();
List<String> lst_names = [];
for (playListObject in homePage.musicPlaylists.playlists)
lst_names.add(playListObject.playlistName);
print("Buttom titles");
print(lst_names);
return lst_names;
} else {
print("no response");
return null;
}
}
static Future<List<String>> loadDataForPlaylistDetailsForCount() async {
var res = await http
.get(url, headers: {'Authorization': dartJsonWebTokenGenerator()});
if (res.statusCode == 200) {
print("response is there");
final homePage = homePageFromJson(res.body);
Playlist playListObject = new Playlist();
List<String> lst_names = [];
for (playListObject in homePage.musicPlaylists.playlists)
lst_names.add(playListObject.playlistTotalTracks.toString());
print("count");
print(lst_names);
return lst_names;
} else {
print("no response");
return null;
}
}
static Future<List<Playlist>> loadDataForPlaylistDetailsForImageUrl() async {
var res = await http
.get(url, headers: {'Authorization': dartJsonWebTokenGenerator()});
if (res.statusCode == 200) {
print("response is there");
final homePage = homePageFromJson(res.body);
Music musicObject = new Music();
List<Playlist> playlistObj = homePage.musicPlaylists.playlists;
print("category icon object returned");
return playlistObj;
} else {
print("no response");
return null;
}
}
}
This is the main file where I am trying to display in listView.First the data is loaded in initstate and then stored in arrays.But for the last one (the url stuff)I tried with the object it self as things became complicated
#override
void initState() {
// TODO: implement initState
super.initState();
Services.loadDataForPlaylistDetailsForButtomTitle().then((playListNames) {
setState(() {
_playListNames = playListNames ;
});
});
Services.loadDataForPlaylistDetailsForButtomTitle().then((playListCount) {
setState(() {
_playListtotalTracks = playListCount ;
});
});
Services.loadDataForPlaylistDetailsForImageUrl().then((objUrl) {
setState(() {
_obj = objUrl ;
});
});
}
The code for listView Builder:
Container(
height: MediaQuery.of(context).size.height * 0.41,
color: Colors.black,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: _playListImageUrls.length,
itemBuilder: (BuildContext context, int index) => Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
margin: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: MediaQuery.of(context).size.height * 0.34,
child: PhysicalModel(
clipBehavior: Clip.antiAliasWithSaveLayer,
color: Colors.black,
shape: BoxShape.rectangle,
borderRadius: BorderRadius.only(
topRight: Radius.circular(35),
bottomRight: Radius.circular(35)),
child: FadeInImage.assetNetwork(
width: MediaQuery.of(context).size.width * 0.285,
image: _obj[index].playlistImages[index].url,
placeholder: cupertinoActivityIndicator,
fit: BoxFit.fill,
),
),
),
Container(
margin: EdgeInsets.fromLTRB(15, 15, 0, 0),
height: MediaQuery.of(context).size.height * 0.03,
child: Text(
_playListNames[index],
style: TextStyle(color: Colors.white),
)),
Container(
margin: EdgeInsets.fromLTRB(15, 0, 0, 0),
height: MediaQuery.of(context).size.height * 0.02,
child: Text(
_playListtotalTracks[index],
style: TextStyle(color: Colors.white),
))
],
),
),
),
Also I find myself repeating this structures many times.Any suggestions to improvise would be equally welcomed.
I have finally found the solution.The whole point where I was doing the mistake was assuming things as a list of object,rather it was a list of list of single object.
The following modifications were made:
In service file
static Future<List<String>> loadDataForPlaylistDetailsForImageUrl() async {
var res = await http
.get(url, headers: {'Authorization': dartJsonWebTokenGenerator()});
if (res.statusCode == 200) {
print("response is thereeeeeeeee");
final homePage = homePageFromJson(res.body);
Playlist playListObject = new Playlist();
List<String> urlList = [];
List<dynamic> lst_names = [];
for (playListObject in homePage.musicPlaylists.playlists) {
lst_names.add(playListObject.playlistImages);
print(lst_names);
}
//lst_names=
print("objjjjjjjjjjjjjjjjjjjj");
for (var listobj in lst_names) {
for (var obj in listobj) {
print(obj.url.toString());
urlList.add(obj.url.toString());
}
}
return urlList;
} else {
print("no response");
return null;
}
}
Also in main file:
FadeInImage.assetNetwork(
width: MediaQuery.of(context).size.width * 0.285,
image: _musicPlaylistImgUrlList[index],
//_categoryIconfor[index].url,
//_obj[index].playlistImages[index].url,
placeholder: cupertinoActivityIndicator,
fit: BoxFit.none,
),