Flutter how to JSON serialize data form api - json

I am tryin to use model in my flutter app to get this concept up and running in my app. I am quite new to OOP so i want to learn as much as i can. My problem is that i have API response from OpenWeather API my method is calling api getting data. That works fine and the i make manual decode and accessing propetires by hand weather["main"] aa usually with JSON. But what i want is to factor/pre-procesds my JSON by model. Below code is working good but i want to apply concept of using JSON serialization and i have no idea how to start. All my attempts failed...:/
I have generated models with https://app.quicktype.io/ with help of guy form my previous answer.
Model:
import 'dart:convert';
Forcast forcastFromJson(String str) => Forcast.fromJson(json.decode(str));
String forcastToJson(Forcast data) => json.encode(data.toJson());
class Forcast {
String cod;
double message;
int cnt;
List<ListElement> list;
City city;
Forcast({
this.cod,
this.message,
this.cnt,
this.list,
this.city,
});
factory Forcast.fromJson(Map<String, dynamic> json) => new Forcast(
cod: json["cod"],
message: json["message"].toDouble(),
cnt: json["cnt"],
list: new List<ListElement>.from(
json["list"].map((x) => ListElement.fromJson(x))),
city: City.fromJson(json["city"]),
);
Map<String, dynamic> toJson() => {
"cod": cod,
"message": message,
"cnt": cnt,
"list": new List<dynamic>.from(list.map((x) => x.toJson())),
"city": city.toJson(),
};
}
class City {
int id;
String name;
Coord coord;
String country;
City({
this.id,
this.name,
this.coord,
this.country,
});
factory City.fromJson(Map<String, dynamic> json) => new City(
id: json["id"],
name: json["name"],
coord: Coord.fromJson(json["coord"]),
country: json["country"],
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"coord": coord.toJson(),
"country": country,
};
}
class Coord {
double lat;
double lon;
Coord({
this.lat,
this.lon,
});
factory Coord.fromJson(Map<String, dynamic> json) => new Coord(
lat: json["lat"].toDouble(),
lon: json["lon"].toDouble(),
);
Map<String, dynamic> toJson() => {
"lat": lat,
"lon": lon,
};
}
class ListElement {
int dt;
MainClass main;
List<Weather> weather;
Clouds clouds;
Wind wind;
Sys sys;
DateTime dtTxt;
Rain rain;
Rain snow;
ListElement({
this.dt,
this.main,
this.weather,
this.clouds,
this.wind,
this.sys,
this.dtTxt,
this.rain,
this.snow,
});
factory ListElement.fromJson(Map<String, dynamic> json) => new ListElement(
dt: json["dt"],
main: MainClass.fromJson(json["main"]),
weather: new List<Weather>.from(
json["weather"].map((x) => Weather.fromJson(x))),
clouds: Clouds.fromJson(json["clouds"]),
wind: Wind.fromJson(json["wind"]),
sys: Sys.fromJson(json["sys"]),
dtTxt: DateTime.parse(json["dt_txt"]),
rain: json["rain"] == null ? null : Rain.fromJson(json["rain"]),
snow: json["snow"] == null ? null : Rain.fromJson(json["snow"]),
);
Map<String, dynamic> toJson() => {
"dt": dt,
"main": main.toJson(),
"weather": new List<dynamic>.from(weather.map((x) => x.toJson())),
"clouds": clouds.toJson(),
"wind": wind.toJson(),
"sys": sys.toJson(),
"dt_txt": dtTxt.toIso8601String(),
"rain": rain == null ? null : rain.toJson(),
"snow": snow == null ? null : snow.toJson(),
};
}
class Clouds {
int all;
Clouds({
this.all,
});
factory Clouds.fromJson(Map<String, dynamic> json) => new Clouds(
all: json["all"],
);
Map<String, dynamic> toJson() => {
"all": all,
};
}
class MainClass {
double temp;
double tempMin;
double tempMax;
double pressure;
double seaLevel;
double grndLevel;
int humidity;
double tempKf;
MainClass({
this.temp,
this.tempMin,
this.tempMax,
this.pressure,
this.seaLevel,
this.grndLevel,
this.humidity,
this.tempKf,
});
factory MainClass.fromJson(Map<String, dynamic> json) => new MainClass(
temp: json["temp"].toDouble(),
tempMin: json["temp_min"].toDouble(),
tempMax: json["temp_max"].toDouble(),
pressure: json["pressure"].toDouble(),
seaLevel: json["sea_level"].toDouble(),
grndLevel: json["grnd_level"].toDouble(),
humidity: json["humidity"],
tempKf: json["temp_kf"].toDouble(),
);
Map<String, dynamic> toJson() => {
"temp": temp,
"temp_min": tempMin,
"temp_max": tempMax,
"pressure": pressure,
"sea_level": seaLevel,
"grnd_level": grndLevel,
"humidity": humidity,
"temp_kf": tempKf,
};
}
class Rain {
double the3H;
Rain({
this.the3H,
});
factory Rain.fromJson(Map<String, dynamic> json) => new Rain(
the3H: json["3h"] == null ? null : json["3h"].toDouble(),
);
Map<String, dynamic> toJson() => {
"3h": the3H == null ? null : the3H,
};
}
class Sys {
Pod pod;
Sys({
this.pod,
});
factory Sys.fromJson(Map<String, dynamic> json) => new Sys(
pod: podValues.map[json["pod"]],
);
Map<String, dynamic> toJson() => {
"pod": podValues.reverse[pod],
};
}
enum Pod { D, N }
final podValues = new EnumValues({"d": Pod.D, "n": Pod.N});
class Weather {
int id;
MainEnum main;
Description description;
String icon;
Weather({
this.id,
this.main,
this.description,
this.icon,
});
factory Weather.fromJson(Map<String, dynamic> json) => new Weather(
id: json["id"],
main: mainEnumValues.map[json["main"]],
description: descriptionValues.map[json["description"]],
icon: json["icon"],
);
Map<String, dynamic> toJson() => {
"id": id,
"main": mainEnumValues.reverse[main],
"description": descriptionValues.reverse[description],
"icon": icon,
};
}
enum Description {
CLEAR_SKY,
BROKEN_CLOUDS,
LIGHT_RAIN,
MODERATE_RAIN,
FEW_CLOUDS
}
final descriptionValues = new EnumValues({
"broken clouds": Description.BROKEN_CLOUDS,
"clear sky": Description.CLEAR_SKY,
"few clouds": Description.FEW_CLOUDS,
"light rain": Description.LIGHT_RAIN,
"moderate rain": Description.MODERATE_RAIN
});
enum MainEnum { CLEAR, CLOUDS, RAIN }
final mainEnumValues = new EnumValues({
"Clear": MainEnum.CLEAR,
"Clouds": MainEnum.CLOUDS,
"Rain": MainEnum.RAIN
});
class Wind {
double speed;
double deg;
Wind({
this.speed,
this.deg,
});
factory Wind.fromJson(Map<String, dynamic> json) => new Wind(
speed: json["speed"].toDouble(),
deg: json["deg"].toDouble(),
);
Map<String, dynamic> toJson() => {
"speed": speed,
"deg": deg,
};
}
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;
}
}
Network to make API call:
import 'package:http/http.dart' as http;
import 'dart:convert';
class NetworkHelper {
NetworkHelper({this.text});
String text;
String apiKey = '';
Future<dynamic> getData(text) async {
http.Response response = await http.get(
'https://api.openweathermap.org/data/2.5/weather?q=$text&appid=$apiKey&units=metric');
if (response.statusCode == 200) {
var decodedData = jsonDecode(response.body);
return decodedData;
} else {
print(response.statusCode);
}
}
Future<dynamic> getForcast(text) async {
http.Response response = await http.get(
'http://api.openweathermap.org/data/2.5/forecast?q=${text}&units=metric&appid=$apiKey');
if (response.statusCode == 200) {
var decodedData = jsonDecode(response.body);
return decodedData;
} else {
print(response.statusCode);
}
}
Future<dynamic> getDataLocation(lat, lon) async {
http.Response response = await http.get(
'https://api.openweathermap.org/data/2.5/weather?lat=$lat&lon=$lon&appid=$apiKey&units=metric');
if (response.statusCode == 200) {
var decodedData = jsonDecode(response.body);
return decodedData;
} else {
print(response.statusCode);
}
}
Future<dynamic> getForcastLocation(lat, lon) async {
http.Response response = await http.get(
'http://api.openweathermap.org/data/2.5/forecast?lat=$lat&lon=$lon&units=metric&appid=$apiKey');
if (response.statusCode == 200) {
var decodedData = jsonDecode(response.body);
return decodedData;
} else {
print(response.statusCode);
}
}
}
Weather where i display data:
import 'package:flutter/material.dart';
import 'package:weather/common/format.dart';
import 'package:weather/service/Network.dart';
import 'package:weather/service/location.dart';
class Weather extends StatefulWidget {
Weather({this.text});
final String text;
_WeatherState createState() => _WeatherState();
}
class _WeatherState extends State<Weather> {
NetworkHelper networkHelper = NetworkHelper();
Location location = Location();
Formats formats = Formats();
int temperature;
String cityName;
String description;
bool isLoading = true;
dynamic newData;
String city;
#override
void initState() {
super.initState();
city = widget.text;
buildUI(city);
}
buildUI(String text) async {
var weatherData = await networkHelper.getData(text);
var forecastData = await networkHelper.getForcast(text);
double temp = weatherData['main']['temp'];
temperature = temp.toInt();
cityName = weatherData['name'];
description = weatherData['weather'][0]['description'];
newData = forecastData['list'].toList();
setState(() {
isLoading = false;
});
}
buildUIByLocation() async {
await location.getCurrentLocation();
var weatherLocation = await networkHelper.getDataLocation(
location.latitude, location.longitude);
var forcastLocation = await networkHelper.getForcastLocation(
location.latitude, location.longitude);
double temp = weatherLocation['main']['temp'];
temperature = temp.toInt();
cityName = weatherLocation['name'];
description = weatherLocation['weather'][0]['description'];
newData = forcastLocation['list'].toList();
setState(() {
isLoading = false;
});
}
Widget get _pageToDisplay {
if (isLoading == true) {
return _loadingView;
} else {
return _weatherView;
}
}
Widget get _loadingView {
return Center(child: CircularProgressIndicator());
}
Widget get _weatherView {
return SafeArea(
child: Column(
children: <Widget>[
Flexible(
flex: 1,
child: Container(
margin: EdgeInsets.fromLTRB(12, 1, 30, 0),
decoration: new BoxDecoration(
color: Color(0xff4556FE),
borderRadius: BorderRadius.all(Radius.circular(10.0)),
boxShadow: [
BoxShadow(
color: Color(0xFFD4DAF6),
offset: Offset(20, 20),
),
BoxShadow(
color: Color(0xFFadb6ff),
offset: Offset(10, 10),
),
],
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
'$cityName',
style: TextStyle(fontSize: 25, color: Colors.white),
),
SizedBox(
height: 5,
),
Text(
'$temperature°C',
style: TextStyle(fontSize: 50, color: Colors.white),
),
],
),
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
'$description',
style: TextStyle(fontSize: 25, color: Colors.white),
),
],
),
)
],
),
),
),
SizedBox(
height: 30,
),
Flexible(
flex: 2,
child: Container(
margin: EdgeInsets.fromLTRB(12, 10, 12, 0),
decoration: new BoxDecoration(
color: Color(0xff4556FE),
borderRadius: BorderRadius.vertical(top: Radius.circular(10.0)),
),
child: ListView.builder(
padding: const EdgeInsets.all(8.0),
itemCount: newData.length,
itemBuilder: (BuildContext context, int index) {
return Container(
margin: const EdgeInsets.all(4.0),
height: 50,
child: Center(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Text(
formats.readTimeStamp(newData[index]['dt']),
style: TextStyle(
color: Colors.white, fontSize: 14),
),
Text(
newData[index]['weather'][0]['main'].toString(),
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.w600),
),
Text(
formats.floatin(newData[index]['main']['temp']),
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w600),
),
],
),
));
}),
),
),
],
),
);
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
IconButton(
padding: EdgeInsets.fromLTRB(0, 0, 20, 0),
icon: Icon(Icons.autorenew, color: Colors.black, size: 30),
onPressed: () {
if (city == "") {
setState(() {
isLoading = true;
buildUIByLocation();
});
} else {
setState(() {
isLoading = true;
buildUI(city);
});
}
},
),
IconButton(
padding: EdgeInsets.fromLTRB(0, 0, 15, 0),
icon: Icon(
Icons.location_on,
color: Colors.black,
size: 30,
),
onPressed: () async {
setState(() {
city = '';
isLoading = true;
});
await buildUIByLocation();
},
)
],
leading: IconButton(
icon: Icon(Icons.arrow_back_ios, color: Colors.black),
onPressed: () {
Navigator.pop(context);
},
),
elevation: 0,
backgroundColor: Colors.transparent,
title: const Text(
'Change location',
style: TextStyle(color: Colors.black),
),
),
body: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(color: Color(0xFFfafafa)),
child: Padding(
padding: const EdgeInsets.fromLTRB(5, 20, 5, 0),
child: Center(child: _pageToDisplay),
),
)
],
),
);
}
}

This is a really basic example. Here you see the Car model class and his basic attributes. Data would be fetching by CarRepository class, this class do network stuff and map data from json to model.
The CarScreen class is an Stateful widget and call CarRepository after initState. If data fetched from network, cars would be displayed in an list.
While fetching an loading indicator would displayed.
import 'dart:convert';
import 'package:http/http.dart' as http;
class Car {
//
// Attributes
//
int id;
String name;
String color;
int speed;
//
// Constructor
//
Car({
#required this.id,
#required this.name,
#required this.color,
#required this.speed,
});
// convert Json to an car object object
factory Car.fromJson(Map<String, dynamic> json) {
return Car(
id: json['id'] as int,
name: json['name'] as String,
color: json['color'] as String,
speed: json['speed'] as int,
);
}
}
class CarRepository {
/// Load all cars form api and will convert it
/// to an list of cars.
///
/// {
/// "results": [
/// {
/// "id": 1,
/// "name": "Tesla Model 3",
/// "color": "red",
/// "speed": 225
/// },
/// {
/// "id": 3,
/// "name": "Tesla Model S",
/// "color": "black",
/// "speed": 255
/// }
/// ]
/// }
///
///
static Future<List<Car>> fetchAll() async {
String query = '';
String url = Uri.encodeFull("https://xxx.de/api/cars" + query);
final response = await http.get(url);
if (response.statusCode == 200) {
Map data = json.decode(response.body);
final cars = (data['results'] as List).map((i) => new Car.fromJson(i));
return cars.toList();
} else {
return [];
}
}
}
class CarsScreen extends StatefulWidget {
_CarsScreenState createState() => _CarsScreenState();
}
class _CarsScreenState extends State<CarsScreen> {
bool _isLoading = true;
List<Car> _cars = [];
#override
void initState() {
super.initState();
fetchCars();
}
Future fetchCars() async {
_cars = await CarRepository.fetchAll();
setState(() {
_isLoading = false;
});
}
#override
Widget build(BuildContext context) {
if (_isLoading) {
return Scaffold(
appBar: AppBar(
title: Text('Cars'),
),
body: Container(
child: Center(
child: CircularProgressIndicator(),
),
),
);
} else {
return Scaffold(
appBar: AppBar(
title: Text('Cars'),
),
body: ListView.builder(
itemCount: _cars.length,
itemBuilder: (context, index) {
Car car = _cars[index];
return ListTile(
title: Text(car.name),
subtitle: Text(car.color),
);
},
),
);
}
}
}

This example include nested array with car objects. I hope it will help.
There is an relationship between producer and car.
import 'dart:convert';
import 'package:http/http.dart' as http;
class CarRepository {
/// Load all producers form api and will convert it
/// to an list of producers.
/// [
/// {
/// "id": 1,
/// "name": "Tesla"
/// "cars": [
/// {
/// "id": 1,
/// "name": "Tesla Model 3",
/// "color": "red",
/// "speed": 225
/// },
/// {
/// "id": 3,
/// "name": "Tesla Model S",
/// "color": "black",
/// "speed": 255
/// }
/// ]
/// },
/// {
/// "id": 2,
/// "name": "Volkswagen"
/// "cars": [
/// {
/// "id": 1,
/// "name": "Golf",
/// "color": "red",
/// "speed": 225
/// },
/// {
/// "id": 3,
/// "name": "Passat",
/// "color": "black",
/// "speed": 255
/// }
/// ]
/// }
/// ]
///
///
static Future<List<Car>> fetchAll() async {
String query = '';
String url = Uri.encodeFull("https://xxx.de/api/producers" + query);
final response = await http.get(url);
if (response.statusCode == 200) {
Map data = json.decode(response.body);
final cars = (data as List).map((i) => new Car.fromJson(i));
return cars.toList();
} else {
return [];
}
}
}
class Producer {
//
// Attributes
//
int id;
String name;
List<Car> cars;
//
// Constructor
//
Producer({
#required this.id,
#required this.name,
#required this.cars,
});
// convert Json to an producer object object
factory Producer.fromJson(Map<String, dynamic> json) {
return Producer(
id: json['id'] as int,
name: json['name'] as String,
cars: (json['cars'] as List ?? []).map((c) {
return Car.fromJson(c);
}).toList(),
);
}
}
class Car {
//
// Attributes
//
int id;
String name;
String color;
int speed;
//
// Constructor
//
Car({
#required this.id,
#required this.name,
#required this.color,
#required this.speed,
});
// convert Json to an car object object
factory Car.fromJson(Map<String, dynamic> json) {
return Car(
id: json['id'] as int,
name: json['name'] as String,
color: json['color'] as String,
speed: json['speed'] as int,
);
}
}

Related

How to setState JSON in DropDownField?

// ignore_for_file: prefer_const_constructors, avoid_unnecessary_containers, prefer_const_literals_to_create_immutables, import_of_legacy_library_into_null_safe, non_constant_identifier_names, unused_field, avoid_print
import 'dart:convert';
import 'package:dropdownfield/dropdownfield.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class FoodWidget extends StatefulWidget {
const FoodWidget({Key? key}) : super(key: key);
#override
_FoodWidgetState createState() => _FoodWidgetState();
}
class _FoodWidgetState extends State<FoodWidget> {
#override
void initState() {
fetchFood();
super.initState();
}
String? food_id;
List food = [];
Future<void> fetchFood() async {
final String response =
await rootBundle.loadString('assets/list_food.json');
final data = await json.decode(response);
print(data);
setState(() {
food = data["food"];
});
}
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(15.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
DropDownField(
onValueChanged: (dynamic value) {
food_id = value;
},
value: food_id,
required: false,
labelText: 'Search food',
items: food,
),
]),
);
}
}
and this is the JSON file. I want to get only names in DropDownField but I can't do it. At the setState function, I really don't know how to put it.
{
"food": [
{
"id": 1,
"name": "coca-cola",
"calories": 120
},
{
"id": 2,
"name": "egg",
"calories": 80
},
{
"id": 3,
"name": "rice",
"calories": 100
}
]
}
I tried to print(data) to test the output. It's all coming out of the domain name, but I want to use that inside. And I really don't know how to do it.
PS. I really will appreciate with answers and suggestions.
you would just need to map the data to get only its name :
Future<void> fetchFood() async {
final String response =
await rootBundle.loadString('assets/list_food.json');
final data = await json.decode(response);
print(data);
setState(() {
food = data["food"].map((e)=>e['name']).toList();
});
}
There after getting the list of foods, you map each item to get only the food name, which is what you need.
As a sidenote
I would recommend that in the future you create a model like :
class Food {
Food({
this.id,
this.name,
this.calories,
});
int id;
String name;
int calories;
factory Food.fromJson(Map<String, dynamic> json) => Food(
id: json["id"],
name: json["name"],
calories: json["calories"],
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"calories": calories,
};
}
So you have a strongly typed List<Food> food and you could access parameters in a type safe matter.
You need to Generate Food class
class Food {
String? id;
String? name;
String? calories;
Food({
this.id,
this.name,
this.calories,
});
Map<String, dynamic> toMap() {
return {
'id': id,
'name': name,
'calories': calories,
};
}
factory Food.fromMap(Map<String, dynamic> map) {
return Food(
id: map['id'],
name: map['name'],
calories: map['calories'],
);
}
String toJson() => json.encode(toMap());
factory Food.fromJson(String source) => Food.fromMap(json.decode(source));
}
Full Code here:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class FoodWidget extends StatefulWidget {
const FoodWidget({Key? key}) : super(key: key);
#override
_FoodWidgetState createState() => _FoodWidgetState();
}
class _FoodWidgetState extends State<FoodWidget> {
#override
void initState() {
fetchFood();
super.initState();
}
String? food_id;
Food? selected_food ;
List<Food> food = [];
Future<void> fetchFood() async {
final String response =
await rootBundle.loadString('assets/list_food.json');
final data = await json.decode(response) as List;
print(data);
setState(() {
food = data.map((e) => Food.fromJson(e)).toList();
});
}
#override
Widget build(BuildContext context) {
return Container(
padding:const EdgeInsets.all(15.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
DropdownButton<Food>(
focusColor: Colors.white,
value: selected_food,
//elevation: 5,
style: const TextStyle(color: Colors.white),
iconEnabledColor: Colors.black,
underline: const SizedBox.shrink(),
items: food.map<DropdownMenuItem<Food>>(
(Food value) {
return DropdownMenuItem<Food>(
value: value,
child: Text(
value.name!,
style: const TextStyle(color: Colors.black),
),
);
}).toList(),
hint: const Text(
"Select Shop Category",
style: TextStyle(
color: Colors.black38,
),
),
onChanged: (Food? value) {
setState(() {
selected_food= value!;
});
},
),
]),
);
}
}
class Food {
String? id;
String? name;
String? calories;
Food({
this.id,
this.name,
this.calories,
});
Map<String, dynamic> toMap() {
return {
'id': id,
'name': name,
'calories': calories,
};
}
factory Food.fromMap(Map<String, dynamic> map) {
return Food(
id: map['id'],
name: map['name'],
calories: map['calories'],
);
}
String toJson() => json.encode(toMap());
factory Food.fromJson(String source) =>
Food.fromMap(json.decode(source));
}

There should be exactly one item with [DropdownButton]'s value: Instance of 'Partner'

My dropdown working as expected . but when I selected a item my app crashing with error
There should be exactly one item with [DropdownButton]'s value: Instance of 'Partner'.
Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
First I declare my variable in class
class _MultipleTestBookingState extends State<MultipleTestBooking> {
Partner? _selectedLab;
Datum? _selectedTest;
....................
declare with Partner?_selectedLab; because my dropdown menu takes in a list of Partners
Then using this variable to show the selected value in my dropdown
Container(
child: FutureBuilder<List<Partner>>(
future: AllPathLab(),
builder:
(BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState !=ConnectionState.done) {
return CircularProgressIndicator();
}
if (snapshot.hasError) {
return Text("Somthing went wrong");
}
if (snapshot.hasData) {
return DropdownButton<Partner>(
value: _selectedLab,
hint: Text("Select Lab"),
items: snapshot.data.map((Partner data) =>
DropdownMenuItem<Partner>(
child: Text("${data.partnerName}"),
value: data,
)
).toList().cast<DropdownMenuItem<Partner>>(),
onChanged: (value){
setState(() {
_selectedLab=value;
encLabId = value!.encPartnerId;
GetTestByLab();
});
}
);
}
return Text("Waiting for Internet Connection");
},
),
),
Full code with my JSON response
So from the data that you provided i have created the code below:
import 'package:date_time_picker/date_time_picker.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app/Patner.dart';
import 'package:flutter_app/dataModel.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
home: MyApp(),
));
}
class MyApp extends StatefulWidget {
const MyApp({Key key}) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Partner _selectedLab;
Datum _selectedTest;
Future getAllPathLabResults;
Future getTestByLabResult;
String encLabId = '';
void initState() {
super.initState();
getAllPathLabResults = allPathLab();
getTestByLabResult = getTestByLab();
}
String _selectedDate = DateTime.now().toString();
Future<List<Partner>> allPathLab() async {
String jsonData = jsonstring;
final model = modelFromJson(jsonData);
print("This is the list length : ${model.partner.length}");
List<Partner> arrData = model.partner;
// this Future is for sample as you will be fetching the api data remove this one
Future.delayed(Duration(seconds: 3));
return arrData;
}
Future<List<Datum>> getTestByLab() async {
print("This is the Id :$encLabId");
_selectedTest = null;
var response = await http.post(
Uri.parse("http://medbo.digitalicon.in/api/medboapi/GetTestByLab"),
body: ({"EncId": encLabId}));
if (response.statusCode == 200) {
final dataModel = dataModelFromJson(response.body);
print(dataModel.data.length);
for (final item in dataModel.data) {
print("This is hte test name :${item.testName}");
}
List<Datum> arrData = dataModel.data;
return arrData;
}
return [];
}
#override
Widget build(BuildContext context) {
var screenWidth = MediaQuery.of(context).size.width;
var screenHeight = MediaQuery.of(context).size.height;
var blockSizeHorizontal = (screenWidth / 100);
var blockSizeVertical = (screenHeight / 100);
return Scaffold(
body: SafeArea(
child: Container(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: ListTile(
title: Text("Booking Information",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: blockSizeHorizontal * 5,
fontFamily: 'Poppins',
color: Theme.of(context).primaryColor,
)),
subtitle: Text("Preferred Visit Date"),
),
),
Container(
margin: EdgeInsets.only(left: 20),
padding: EdgeInsets.only(left: 0, right: 150),
decoration: BoxDecoration(
color: Colors.lightBlue[50],
borderRadius: BorderRadius.all(Radius.circular(12)),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: DateTimePicker(
initialValue: DateTime.now().toString(),
//initialValue:'', // initialValue or controller.text can be null, empty or a DateTime string otherwise it will throw an error.
type: DateTimePickerType.date,
dateLabelText: 'Select Date',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: blockSizeHorizontal * 3.5,
fontFamily: 'Poppins',
color: Colors.green,
letterSpacing: 2.0,
),
firstDate: DateTime.now(),
lastDate: DateTime.now().add(Duration(days: 30)),
// This will add one year from current date
validator: (value) {
return null;
},
onChanged: (value) {
if (value.isNotEmpty) {
setState(() {
_selectedDate = value;
});
}
},
onSaved: (value) {
if (value.isNotEmpty) {
_selectedDate = value;
}
},
),
),
),
ListTile(
title: Text(
"Select Pathological Lab",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: blockSizeHorizontal * 4.0,
fontFamily: 'Poppins',
color: Theme.of(context).primaryColor,
),
),
),
Container(
child: FutureBuilder<List<Partner>>(
future: getAllPathLabResults,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return CircularProgressIndicator();
}
if (snapshot.hasError) {
return Text("Somthing went wrong");
}
if (snapshot.hasData) {
List<Partner> data =
snapshot.hasData ? snapshot.data : [];
return DropdownButton<Partner>(
value: _selectedLab,
hint: Text("Select Lab"),
//underline: SizedBox(),
//isExpanded: true,
items: data
.map((Partner data) => DropdownMenuItem<Partner>(
child: Text("${data.partnerName}"),
value: data,
))
.toList()
.cast<DropdownMenuItem<Partner>>(),
onChanged: (value) {
setState(() {
_selectedLab = value;
encLabId = value.encPartnerId;
getTestByLabResult = getTestByLab();
});
//GetTestByLab(value!.encPartnerId); // passing encid to my next API function
// GetTestByLab();
},
);
}
return Text("Waiting for Internet Connection");
},
),
),
//=========================================================== Dependent drop down===================================
ListTile(
title: Text(
"Test Name",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: blockSizeHorizontal * 4.0,
fontFamily: 'Poppins',
color: Theme.of(context).primaryColor,
),
),
),
Container(
child: FutureBuilder<List<Datum>>(
future: getTestByLabResult,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return CircularProgressIndicator();
}
if (snapshot.hasError) {
return Text("Select a Lab for your Test");
}
if (snapshot.hasData) {
List<Datum> data = snapshot.hasData ? snapshot.data : [];
return DropdownButton<Datum>(
value: _selectedTest,
hint: Text(""),
//underline: SizedBox(),
//isExpanded: true,
items: data
.map((Datum data) => DropdownMenuItem<Datum>(
child: Text("${data.testName}"),
value: data,
))
.toList()
.cast<DropdownMenuItem<Datum>>(),
onChanged: (value) {
print("This is the value : ${value.testName}");
setState(() {
_selectedTest = value;
});
//GetTestByLab(value!.encPartnerId); // passing encid to my next API function
});
}
return Text("Waiting for Internet Connection");
},
),
),
],
),
),
),
);
}
}
// used this as a sample
String jsonstring = '''{
"Status": "1",
"Message": "",
"Partner": [
{
"EncPartnerId": "IujyQXg8KZg8asLvK/FS7g==",
"PartnerName": "dasfdsf"
},
{
"EncPartnerId": "pEl2B9kuumKRxIxLJO76eQ==",
"PartnerName": "partner172"
},
{
"EncPartnerId": "eYwtNBXR6P/JDtsIwr+Bvw==",
"PartnerName": "nnkb"
},
{
"EncPartnerId": "kFgorcFF0G6RQD4W+LwWnQ==",
"PartnerName": "nnkjj"
},
{
"EncPartnerId": "U4exk+vfMGrn7cjNUa/PBw==",
"PartnerName": "mahadev"
},
{
"EncPartnerId": "tqkaSjTFgDf0612mp9mbsQ==",
"PartnerName": null
},
{
"EncPartnerId": "0aruO0FbYOu5IerRBxdT8w==",
"PartnerName": "Suraksha Diagnostics"
},
{
"EncPartnerId": "65gtodyhbtdInTsJWr1ZkA==",
"PartnerName": "Rasomoy pvt. Hospital"
},
{
"EncPartnerId": "LEuT1eIlpLEMAAkZme3wpQ==",
"PartnerName": "Tangra medical House"
},
{
"EncPartnerId": "q8O8YMzYKXSB4RtkX4k7Lw==",
"PartnerName": "Partner new"
}
]
}''';
Models for the apis:
// To parse this JSON data, do
//
// final model = modelFromJson(jsonString);
import 'dart:convert';
Model modelFromJson(String str) => Model.fromJson(json.decode(str));
String modelToJson(Model data) => json.encode(data.toJson());
class Model {
Model({
this.status,
this.message,
this.partner,
});
String status;
String message;
List<Partner> partner;
factory Model.fromJson(Map<String, dynamic> json) => Model(
status: json["Status"],
message: json["Message"],
partner:
List<Partner>.from(json["Partner"].map((x) => Partner.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"Status": status,
"Message": message,
"Partner": List<dynamic>.from(partner.map((x) => x.toJson())),
};
}
class Partner {
Partner({
this.encPartnerId,
this.partnerName,
});
String encPartnerId;
String partnerName;
factory Partner.fromJson(Map<String, dynamic> json) => Partner(
encPartnerId: json["EncPartnerId"],
partnerName: json["PartnerName"] == null ? null : json["PartnerName"],
);
Map<String, dynamic> toJson() => {
"EncPartnerId": encPartnerId,
"PartnerName": partnerName == null ? null : partnerName,
};
}
second api parsing model
// To parse this JSON data, do
//
// final dataModel = dataModelFromJson(jsonString);
import 'dart:convert';
DataModel dataModelFromJson(String str) => DataModel.fromJson(json.decode(str));
String dataModelToJson(DataModel data) => json.encode(data.toJson());
class DataModel {
DataModel({
this.status,
this.message,
this.data,
});
String status;
String message;
List<Datum> data;
factory DataModel.fromJson(Map<String, dynamic> json) => DataModel(
status: json["Status"],
message: json["Message"],
data: json["Data"] == null
? []
: List<Datum>.from(json["Data"].map((x) => Datum.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"Status": status,
"Message": message,
"Data":
data == null ? [] : List<dynamic>.from(data.map((x) => x.toJson())),
};
}
class Datum {
Datum({
this.testId,
this.encTestId,
this.testName,
this.noOfPartner,
this.testFee,
this.discountedFee,
this.bookingFee,
this.reportTime,
this.note,
this.createBy,
this.createDate,
this.modBy,
this.modDate,
this.activeStatus,
this.permission,
});
String testId;
dynamic encTestId;
String testName;
dynamic noOfPartner;
dynamic testFee;
dynamic discountedFee;
dynamic bookingFee;
dynamic reportTime;
dynamic note;
dynamic createBy;
dynamic createDate;
dynamic modBy;
dynamic modDate;
dynamic activeStatus;
dynamic permission;
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
testId: json["TestId"],
encTestId: json["EncTestId"],
testName: json["TestName"],
noOfPartner: json["NoOfPartner"],
testFee: json["TestFee"],
discountedFee: json["DiscountedFee"],
bookingFee: json["BookingFee"],
reportTime: json["ReportTime"],
note: json["Note"],
createBy: json["CreateBy"],
createDate: json["CreateDate"],
modBy: json["ModBy"],
modDate: json["ModDate"],
activeStatus: json["ActiveStatus"],
permission: json["Permission"],
);
Map<String, dynamic> toJson() => {
"TestId": testId,
"EncTestId": encTestId,
"TestName": testName,
"NoOfPartner": noOfPartner,
"TestFee": testFee,
"DiscountedFee": discountedFee,
"BookingFee": bookingFee,
"ReportTime": reportTime,
"Note": note,
"CreateBy": createBy,
"CreateDate": createDate,
"ModBy": modBy,
"ModDate": modDate,
"ActiveStatus": activeStatus,
"Permission": permission,
};
}
So when you initially fetch the data based on the id and select the second dropdown. now when you change the lab you have the make the selected text to null.
and you are are also using the futurebuilder method in wrong manner as there is setstate getting called it is creating multiple rebuids and giving error.
please run the code and check if its working.

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,
),

How to display in widget the complex JSON using flutter?

My problem is i don't know how to display the Object inside the Object of JSON.
But i already display the Outer Object like name, usermae etc. And i want to display the object inside the Address and Geo. Im new to JSON and flutter please guide me
i read this but i dont know what i need here
the code is from here
JSON OUTPUT json is from here
[
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere#april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
},
]
MODEL
i generate my model in here
import 'dart:convert';
List<UserModel> userModelFromJson(String str) =>
List<UserModel>.from(json.decode(str).map((x) => UserModel.fromJson(x)));
String userModelToJson(List<UserModel> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class UserModel {
int id;
String name;
String username;
String email;
Address address;
String phone;
String website;
Company company;
UserModel({
this.id,
this.name,
this.username,
this.email,
this.address,
this.phone,
this.website,
this.company,
});
factory UserModel.fromJson(Map<String, dynamic> json) => UserModel(
id: json["id"],
name: json["name"],
username: json["username"],
email: json["email"],
address: Address.fromJson(json["address"]),
phone: json["phone"],
website: json["website"],
company: Company.fromJson(json["company"]),
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"username": username,
"email": email,
"address": address.toJson(),
"phone": phone,
"website": website,
"company": company.toJson(),
};
}
class Address {
String street;
String suite;
String city;
String zipcode;
Geo geo;
Address({
this.street,
this.suite,
this.city,
this.zipcode,
this.geo,
});
factory Address.fromJson(Map<String, dynamic> json) => Address(
street: json["street"],
suite: json["suite"],
city: json["city"],
zipcode: json["zipcode"],
geo: Geo.fromJson(json["geo"]),
);
Map<String, dynamic> toJson() => {
"street": street,
"suite": suite,
"city": city,
"zipcode": zipcode,
"geo": geo.toJson(),
};
}
class Geo {
String lat;
String lng;
Geo({
this.lat,
this.lng,
});
factory Geo.fromJson(Map<String, dynamic> json) => Geo(
lat: json["lat"],
lng: json["lng"],
);
Map<String, dynamic> toJson() => {
"lat": lat,
"lng": lng,
};
}
class Company {
String name;
String catchPhrase;
String bs;
Company({
this.name,
this.catchPhrase,
this.bs,
});
factory Company.fromJson(Map<String, dynamic> json) => Company(
name: json["name"],
catchPhrase: json["catchPhrase"],
bs: json["bs"],
);
Map<String, dynamic> toJson() => {
"name": name,
"catchPhrase": catchPhrase,
"bs": bs,
};
}
Services.dart
class Services {
static const String url = 'https://jsonplaceholder.typicode.com/users';
static Future<List<UserModel>> getUsers() async {
try {
final response = await http.get(url);
if (200 == response.statusCode) {
final List<UserModel> users = userModelFromJson(response.body);
return users;
} else {
return List<UserModel>();
}
} catch (e) {
return List<UserModel>();
}
}
}
HomeView.dart
class _HomeViewState extends State<HomeView> {
List<UserModel> _users;
bool _loading;
#override
void initState() {
super.initState();
_loading = true;
Services.getUsers().then((users) {
setState(() {
_users = users;
_loading = false;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_loading ? 'Loading...' : 'Users'),
),
body: Container(
color: Colors.white,
child: ListView.builder(
itemCount: _users == null ? 0 : _users.length,
itemBuilder: (context, index) {
UserModel user = _users[index];
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
ListTile(
title: Text(user.name),
subtitle: Text(user.email),
trailing: Text(user.phone),
),
],
);
},
),
),
);
}
}
Thank you for your kindness
The model that you create is correct, you have (Good habit) only to check the objects inside your model before you parse them
UserModel.fromJson(Map<String, dynamic> json) {
// ...
address =
json['address'] != null ? new Address.fromJson(json['address']) : null;
company =
json['company'] != null ? new Company.fromJson(json['company']) : null;
// ...
}
On your service class use the fetch way that is set on flutter documentation to simplify your code
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<List<UserModel>> fetchUsers(http.Client client) async {
final response =
await client.get('https://jsonplaceholder.typicode.com/users');
return parseUsers(response.body);
}
List<UserModel> parseUsers(String responseBody) {
final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<UserModel>((json) => UserModel.fromJson(json)).toList();
}
and once you get the data from json you can access to every object based on the hierarchy inside the json, in your case the stateful widget would look like, where i replace the name and the phone with latitude inside the geo and city inside the address
class _HomeViewState extends State<HomeView> {
List<UserModel> _users;
bool _loading;
#override
void initState() {
super.initState();
_loading = true;
fetchUsers(http.Client()).then((users) {
setState(() {
_users = users;
_loading = false;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_loading ? 'Loading...' : 'Users'),
),
body: Container(
color: Colors.white,
child: ListView.builder(
itemCount: _users == null ? 0 : _users.length,
itemBuilder: (context, index) {
UserModel user = _users[index];
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
ListTile(
title: Text(user.name),
subtitle: Text(user.address.geo.lat),
trailing: Text(user.address.city),
),
],
);
},
),
),
);
}
}
I hope this help
You can copy paste run full code below
You can directly assign attribute
code snippet
title: Text('${user.name} ${user.address.city} ${user.address.geo.lat}'),
working demo
full code
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
List<UserModel> userModelFromJson(String str) =>
List<UserModel>.from(json.decode(str).map((x) => UserModel.fromJson(x)));
String userModelToJson(List<UserModel> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class UserModel {
int id;
String name;
String username;
String email;
Address address;
String phone;
String website;
Company company;
UserModel({
this.id,
this.name,
this.username,
this.email,
this.address,
this.phone,
this.website,
this.company,
});
factory UserModel.fromJson(Map<String, dynamic> json) => UserModel(
id: json["id"],
name: json["name"],
username: json["username"],
email: json["email"],
address: Address.fromJson(json["address"]),
phone: json["phone"],
website: json["website"],
company: Company.fromJson(json["company"]),
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"username": username,
"email": email,
"address": address.toJson(),
"phone": phone,
"website": website,
"company": company.toJson(),
};
}
class Address {
String street;
String suite;
String city;
String zipcode;
Geo geo;
Address({
this.street,
this.suite,
this.city,
this.zipcode,
this.geo,
});
factory Address.fromJson(Map<String, dynamic> json) => Address(
street: json["street"],
suite: json["suite"],
city: json["city"],
zipcode: json["zipcode"],
geo: Geo.fromJson(json["geo"]),
);
Map<String, dynamic> toJson() => {
"street": street,
"suite": suite,
"city": city,
"zipcode": zipcode,
"geo": geo.toJson(),
};
}
class Geo {
String lat;
String lng;
Geo({
this.lat,
this.lng,
});
factory Geo.fromJson(Map<String, dynamic> json) => Geo(
lat: json["lat"],
lng: json["lng"],
);
Map<String, dynamic> toJson() => {
"lat": lat,
"lng": lng,
};
}
class Company {
String name;
String catchPhrase;
String bs;
Company({
this.name,
this.catchPhrase,
this.bs,
});
factory Company.fromJson(Map<String, dynamic> json) => Company(
name: json["name"],
catchPhrase: json["catchPhrase"],
bs: json["bs"],
);
Map<String, dynamic> toJson() => {
"name": name,
"catchPhrase": catchPhrase,
"bs": bs,
};
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: HomeView(title: 'Flutter Demo Home Page'),
);
}
}
class Services {
static const String url = 'https://jsonplaceholder.typicode.com/users';
static Future<List<UserModel>> getUsers() async {
try {
final response = await http.get(url);
if (200 == response.statusCode) {
final List<UserModel> users = userModelFromJson(response.body);
return users;
} else {
return List<UserModel>();
}
} catch (e) {
return List<UserModel>();
}
}
}
class HomeView extends StatefulWidget {
HomeView({Key key, this.title}) : super(key: key);
final String title;
#override
_HomeViewState createState() => _HomeViewState();
}
class _HomeViewState extends State<HomeView> {
List<UserModel> _users;
bool _loading;
#override
void initState() {
super.initState();
_loading = true;
Services.getUsers().then((users) {
setState(() {
_users = users;
_loading = false;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_loading ? 'Loading...' : 'Users'),
),
body: Container(
color: Colors.white,
child: ListView.builder(
itemCount: _users == null ? 0 : _users.length,
itemBuilder: (context, index) {
UserModel user = _users[index];
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
ListTile(
title: Text('${user.name} ${user.address.city} ${user.address.geo.lat}'),
subtitle: Text(user.email),
trailing: Text(user.phone),
),
],
);
},
),
),
);
}
}

How to Parse Nested JSON

I'm able to parse the JSON using following code,
Map<String, dynamic> map = jsonDecode(response.body); // import 'dart:convert';
List<dynamic> datalist = map['data'];
I got List dynamic but i need data list
My problem is if I get product items in data list then how should i parse the JSON. I got stuck here.
When it comes to nested array of JSON, how to parse it.
**
{
"status": 0,
"message": "Product Not Found",
"data": [{
"id": "1",
"product_name": "Pet 0.5",
"qty": "500",
"unit": "ml",
"product_img": "SRC.jpg",
"description": "sgsdgdfhdfhh",
"sale_price": "100",
"donation_amt": "10"
},
{
"id": "7",
"product_name": "Pet 1l",
"qty": "1",
"unit": "l",
"product_img": "SRC1.jpg",
"description": "dgdg",
"sale_price": "20",
"donation_amt": "1"
}
]
}
**
My dart code for the JSON
class ProductList {
int status;
String message;
List<Data> data;
ProductList({this.status, this.message, this.data});
ProductList.fromJson(Map<String, dynamic> json) {
status = json['status'];
message = json['message'];
if (json['data'] != null) {
data = new List<Data>();
json['data'].forEach((v) {
data.add(new Data.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['status'] = this.status;
data['message'] = this.message;
if (this.data != null) {
data['data'] = this.data.map((v) => v.toJson()).toList();
}
return data;
}
}
class Data {
String id;
String productName;
String qty;
String unit;
String productImg;
String description;
String salePrice;
String donationAmt;
Data(
{this.id,
this.productName,
this.qty,
this.unit,
this.productImg,
this.description,
this.salePrice,
this.donationAmt});
Data.fromJson(Map<String, dynamic> json) {
id = json['id'];
productName = json['product_name'];
qty = json['qty'];
unit = json['unit'];
productImg = json['product_img'];
description = json['description'];
salePrice = json['sale_price'];
donationAmt = json['donation_amt'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['product_name'] = this.productName;
data['qty'] = this.qty;
data['unit'] = this.unit;
data['product_img'] = this.productImg;
data['description'] = this.description;
data['sale_price'] = this.salePrice;
data['donation_amt'] = this.donationAmt;
return data;
}
}
This is the code below for the drop down list. We need to populate the drop down with the product name and id. The product name and id fields are there in the data part of the JSON
Padding(
padding: const EdgeInsets.fromLTRB(25.0, 20.0, 0, 0),
child: Container(
width: 160,
height: 40,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
border: Border.all(
color: Colors.red,
style: BorderStyle.solid,
width: 0.80),
),
child: DropdownButton<Product>(
value: selectedUser,
icon: Padding(
padding: const EdgeInsets.only(left:15.0),
child: Icon(Icons.arrow_drop_down),
),
iconSize: 25,
underline: SizedBox(),
onChanged: (Product newValue) {
setState(() {
selectedUser = newValue;
});
},
items: users.map((Product user) {
return DropdownMenuItem<Product>(
value: user,
child: Padding(
padding:
const EdgeInsets.only(left: 10.0),
child: Text(
user.name,
style: TextStyle(
fontSize: 18,
color: Colors.black,
),
),
),
);
}).toList()),
),
),
So as you Described i have made some changes and loaded you json locally, you can make a api call and then everything is the same:
{
"status": 0,
"message": "Product Not Found",
"data": [
{
"id": "1",
"product_name": "Pet 0.5",
"qty": "500",
"unit": "ml",
"product_img": "SRC.jpg",
"description": "sgsdgdfhdfhh",
"sale_price": "100",
"donation_amt": "10"
},
{
"id": "7",
"product_name": "Pet 1l",
"qty": "1",
"unit": "l",
"product_img": "SRC1.jpg",
"description": "dgdg",
"sale_price": "20",
"donation_amt": "1"
}
]
}
json you provided
// To parse this JSON data, do
//
// final productList = productListFromJson(jsonString);
import 'dart:convert';
ProductList productListFromJson(String str) =>
ProductList.fromJson(json.decode(str));
String productListToJson(ProductList data) => json.encode(data.toJson());
class ProductList {
int status;
String message;
List<Datum> data;
ProductList({
this.status,
this.message,
this.data,
});
factory ProductList.fromJson(Map<String, dynamic> json) => ProductList(
status: json["status"],
message: json["message"],
data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"status": status,
"message": message,
"data": List<dynamic>.from(data.map((x) => x.toJson())),
};
}
class Datum {
String id;
String productName;
String qty;
String unit;
String productImg;
String description;
String salePrice;
String donationAmt;
Datum({
this.id,
this.productName,
this.qty,
this.unit,
this.productImg,
this.description,
this.salePrice,
this.donationAmt,
});
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
id: json["id"],
productName: json["product_name"],
qty: json["qty"],
unit: json["unit"],
productImg: json["product_img"],
description: json["description"],
salePrice: json["sale_price"],
donationAmt: json["donation_amt"],
);
Map<String, dynamic> toJson() => {
"id": id,
"product_name": productName,
"qty": qty,
"unit": unit,
"product_img": productImg,
"description": description,
"sale_price": salePrice,
"donation_amt": donationAmt,
};
}
creating the model class for the json
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:sample_testing_project/models.dart';
main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _currentSelectedValue;
List<Datum> data = List();
bool _isLoading = false;
String selectedUser;
#override
void initState() {
// TODO: implement initState
super.initState();
loadYourData();
}
Future<String> loadFromAssets() async {
return await rootBundle.loadString('json/parse.json');
}
loadYourData() async {
setState(() {
_isLoading = true;
});
// Loading your json locally you can make an api call, when you get the response just pass it to the productListFromJson method
String jsonString = await loadFromAssets();
final productList = productListFromJson(jsonString);
data = productList.data;
setState(() {
_isLoading = false;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: _isLoading
? Text('Loading')
: Container(
child: Padding(
padding: const EdgeInsets.fromLTRB(25.0, 20.0, 0, 0),
child: Container(
width: 160,
height: 40,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
border: Border.all(
color: Colors.red,
style: BorderStyle.solid,
width: 0.80),
),
child: DropdownButton(
value: selectedUser,
isExpanded: true,
icon: Padding(
padding: const EdgeInsets.only(left: 15.0),
child: Icon(Icons.arrow_drop_down),
),
iconSize: 25,
underline: SizedBox(),
onChanged: (newValue) {
setState(() {
selectedUser = newValue;
});
},
hint: Padding(
padding: const EdgeInsets.all(8.0),
child: Text('Select'),
),
items: data.map((data) {
return DropdownMenuItem(
value: data.id,
child: Padding(
padding: const EdgeInsets.only(left: 10.0),
child: Text(
data.id + ':' + data.productName,
style: TextStyle(
fontSize: 18,
color: Colors.black,
),
),
),
);
}).toList()),
),
),
),
),
);
}
}
check out the changes that i have made using your same ui.
Let me know if its working.
Thanks.
Remember: "JSON is not 'nested.'" When you're given a JSON string, you decode it and this gives you a data-structure ... which very well might be "nested." How to handle that correctly is up to you.
Always treat JSON (or YAML, or XML) as a "black box." Use the utilities provided in the language to encode, decode and parse them.