i have my api which returns the json data, within the json there is multiple nested parts that i want to use. i have my models setup. how do i return them back to my futurebuilder and then use them i.e. snapshot.data['media'][0].fieldname or snapshot.data['locationData'][0].fieldname.
I have change the code back so at the moment it only returns the LocationData but not the MediaData. this is the part i need help with returning all of it at the same time to use on my page.
here is what the json looks like when i get it back from the api
{
"recordsTotal": 1,
"sensordate": "2022-01-20",
"data": [
{
"id": 2,
"locationname": "The Old Man of Storr",
"description": "",
"shortdescription":"",
"latitude": "55.9486",
"longitude": " -3.1910",
"mainimageurl": "",
"road": "",
"addressline1": "",
"addressline2": "",
"town": "",
"county": "",
"postcode": "",
"areaid": 2,
"headerimageid": 450,
"carparkcapacity": 100,
"title": "Old Town",
"originalfilename": "OldTown.jpg",
"ext": "jpg",
"alttext": "Old Town",
"savelocation": "/library/images/locations/",
"filename": "cd8d5c511f3b64758238e75c1aa7c84d"
}
],
"media": [
{
"locationid": 2,
"mediaid": 32,
"title": "Old Town History",
"systemfilename": "/library/media/64c8ba08a781ef8b8b2a08c62d0427b6.mp3",
"transcriptionnotes": "Transcription of media file",
"mediatype": "audio",
"originalfilename": "oldtown.mp3",
"locationname": "Old Town"
}
]
}
//This is my 2 models
class LocationData {
final int id;
final String locationname;
final String description;
final String shortdescription;
final double latitude;
final double longitude;
final String mainimageurl;
final String imagefilename;
final String imagelocation;
final String imageext;
final int carparkcapacity;
final int areaid;
LocationData(
{required this.id,
required this.locationname,
required this.description,
required this.carparkcapacity,
required this.areaid,
required this.imageext,
required this.imagefilename,
required this.imagelocation,
required this.latitude,
required this.longitude,
required this.mainimageurl,
required this.shortdescription,
});
factory LocationData.fromJson(json) => LocationData(
locationname: json['locationname'],
id: json['id'] == null ? 0 : json["id"],
latitude: double.parse(json['latitude']),
longitude: double.parse(json['longitude']),
areaid: json['areaid'] == null ? 0 : json["areaid"],
description: json['description'] == null
? 'Welcome to Skye'
: json["description"],
shortdescription: json['shortdescription'] == null
? 'Welcome'
: json["shortdescription"],
imageext: json['ext'] == null ? 'jpg' : json["ext"],
carparkcapacity:
json['carparkcapacity'] == null ? 0 : json["carparkcapacity"],
imagefilename:
json['filename'] == null ? 'logo' : json["filename"],
imagelocation: json['savelocation'] == null
? '/assets/imgs/'
: json["savelocation"],
mainimageurl: json['mainimageurl'] == null
? '/assets/imgs/logo.jpg'
: json["mainimageurl"],
);
}
//Similar to above
class MediaData{}
//Getting the data
class LocationDataApi {
static Future<List<LocationData>> getLocationData(
String locationName) async {
final hotspotLocationsURL =
'${config.apiUrl}/locations.php?action=get_location&location='
locationName;
try {
final response = await http.get(Uri.parse(hotspotLocationsURL));
if (response.statusCode == 200) {
final body = json.decode(response.body);
//Returned Data
return body['data'].map<LocationData>(LocationData.fromJson).toList();
} else {
throw 'Error Retrieving Data';
}
} catch (e) {
if (kDebugMode) {
print(e);
}
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load Location Data');
}
}
}
on my page
class _AlreadyHereState extends State<AlreadyHere> {
late Future<List<LocationData>> _locationData;
}
....other code
FutureBuilder(
future: _locationData,
builder: (BuildContext context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
} else if (snapshot.error != null) {
return const Center(child: Text('an error occured!'));
} else {
//this part how do i get the data? snapshot.data['media'][0].fieldname doesnt work/
CodePudding user response:
for starters, you can change your model to look this
// To parse this JSON data, do
//
// final someClass = someClassFromJson(jsonString);
import 'package:meta/meta.dart';
import 'dart:convert';
class SomeClass {
SomeClass({
required this.recordsTotal,
required this.sensordate,
required this.data,
required this.media,
});
final int recordsTotal;
final DateTime sensordate;
final List<Datum> data;
final List<Media> media;
factory SomeClass.fromRawJson(String str) => SomeClass.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory SomeClass.fromJson(Map<String, dynamic> json) => SomeClass(
recordsTotal: json["recordsTotal"],
sensordate: DateTime.parse(json["sensordate"]),
data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
media: List<Media>.from(json["media"].map((x) => Media.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"recordsTotal": recordsTotal,
"sensordate": "${sensordate.year.toString().padLeft(4, '0')}-${sensordate.month.toString().padLeft(2, '0')}-${sensordate.day.toString().padLeft(2, '0')}",
"data": List<dynamic>.from(data.map((x) => x.toJson())),
"media": List<dynamic>.from(media.map((x) => x.toJson())),
};
}
class Datum {
Datum({
required this.id,
required this.locationname,
required this.description,
required this.shortdescription,
required this.latitude,
required this.longitude,
required this.mainimageurl,
required this.road,
required this.addressline1,
required this.addressline2,
required this.town,
required this.county,
required this.postcode,
required this.areaid,
required this.headerimageid,
required this.carparkcapacity,
required this.title,
required this.originalfilename,
required this.ext,
required this.alttext,
required this.savelocation,
required this.filename,
});
final int id;
final String locationname;
final String description;
final String shortdescription;
final String latitude;
final String longitude;
final String mainimageurl;
final String road;
final String addressline1;
final String addressline2;
final String town;
final String county;
final String postcode;
final int areaid;
final int headerimageid;
final int carparkcapacity;
final String title;
final String originalfilename;
final String ext;
final String alttext;
final String savelocation;
final String filename;
factory Datum.fromRawJson(String str) => Datum.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
id: json["id"],
locationname: json["locationname"],
description: json["description"],
shortdescription: json["shortdescription"],
latitude: json["latitude"],
longitude: json["longitude"],
mainimageurl: json["mainimageurl"],
road: json["road"],
addressline1: json["addressline1"],
addressline2: json["addressline2"],
town: json["town"],
county: json["county"],
postcode: json["postcode"],
areaid: json["areaid"],
headerimageid: json["headerimageid"],
carparkcapacity: json["carparkcapacity"],
title: json["title"],
originalfilename: json["originalfilename"],
ext: json["ext"],
alttext: json["alttext"],
savelocation: json["savelocation"],
filename: json["filename"],
);
Map<String, dynamic> toJson() => {
"id": id,
"locationname": locationname,
"description": description,
"shortdescription": shortdescription,
"latitude": latitude,
"longitude": longitude,
"mainimageurl": mainimageurl,
"road": road,
"addressline1": addressline1,
"addressline2": addressline2,
"town": town,
"county": county,
"postcode": postcode,
"areaid": areaid,
"headerimageid": headerimageid,
"carparkcapacity": carparkcapacity,
"title": title,
"originalfilename": originalfilename,
"ext": ext,
"alttext": alttext,
"savelocation": savelocation,
"filename": filename,
};
}
class Media {
Media({
required this.locationid,
required this.mediaid,
required this.title,
required this.systemfilename,
required this.transcriptionnotes,
required this.mediatype,
required this.originalfilename,
required this.locationname,
});
final int locationid;
final int mediaid;
final String title;
final String systemfilename;
final String transcriptionnotes;
final String mediatype;
final String originalfilename;
final String locationname;
factory Media.fromRawJson(String str) => Media.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory Media.fromJson(Map<String, dynamic> json) => Media(
locationid: json["locationid"],
mediaid: json["mediaid"],
title: json["title"],
systemfilename: json["systemfilename"],
transcriptionnotes: json["transcriptionnotes"],
mediatype: json["mediatype"],
originalfilename: json["originalfilename"],
locationname: json["locationname"],
);
Map<String, dynamic> toJson() => {
"locationid": locationid,
"mediaid": mediaid,
"title": title,
"systemfilename": systemfilename,
"transcriptionnotes": transcriptionnotes,
"mediatype": mediatype,
"originalfilename": originalfilename,
"locationname": locationname,
};
}
and then inside FutureBuilder use like this
FutureBuilder(
future: _locationData,
// Add <T> to the Asyncsnapshot class
builder: (BuildContext context, AsyncSnapshot<SomeClass> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
} else if (snapshot.error != null) {
return const Center(child: Text('an error occured!'));
} else {
print(snapshot.data.data[0].longitude);
print(snapshot.data.media[0].title);
}