I have the following JSON hosted on localhost and am trying to resolve it in a FutureBuilder widget. I cannot resolve the data from the Json to display using the FutureBuilder widget. All I get is "Instance of LiteratureDataModel". Moreover, I cannot get the length of the data snapshot. The error I get is "The getter length isn't defined for the type Object"
{
"data": [
{
"authors": "author_name1",
"edition": "publication_edition1",
"id": 1,
"pubdate": "publication_date1",
"publisher": "publisher1",
"source": "literature_source1",
"title": "literature_title1"
},
{
"authors": "author_name2",
"edition": "publication_edition2",
"id": 2,
"pubdate": "publication_date2",
"publisher": "publisher2",
"source": "literature_source2",
"title": "literature_title2"
}
]
}
I generated the model class for the above Json using the following link:
Here is the class that was generated. I modified it to use null safety. The list of map objects according to the JSON prints successfully in the LiteratureDataModel factory constructor. So, the data is successfully received
class LiteratureDataModel {
LiteratureDataModel({
this.ultLiteratureDataModel,
});
final List<LiteratureModel>? ultLiteratureDataModel;
factory LiteratureDataModel.fromJson(Map<String, dynamic> json) => LiteratureDataModel(
ultLiteratureDataModel: List<LiteratureModel>.from(json["data"].map((data) {
print(data);
return LiteratureModel.fromJson(data);
})).toList(),
);
Map<String, dynamic> toJson() => {
"data": List<dynamic>.from(ultLiteratureDataModel!.map((data) => data.toJson())),
};
}
class LiteratureModel {
LiteratureModel({
this.authors,
this.edition,
this.id,
this.pubdate,
this.publisher,
this.source,
this.title,
});
final String? authors;
final String? edition;
final int? id;
final String? pubdate;
final String? publisher;
final String? source;
final String? title;
factory LiteratureModel.fromJson(Map<String, dynamic> json) => LiteratureModel(
authors: json["authors"],
edition: json["edition"],
id: json["id"],
pubdate: json["pubdate"],
publisher: json["publisher"],
source: json["source"],
title: json["title"],
);
Map<String, dynamic> toJson() => {
"authors": authors,
"edition": edition,
"id": id,
"pubdate": pubdate,
"publisher": publisher,
"source": source,
"title": title,
};
}
Here is the widget for displaying the data:
class Literature extends StatelessWidget {
final LiteratureService _literatureService = LiteratureService();
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(24.0),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(12)),
),
child: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: FutureBuilder(
future: _literatureService.fetchLiterature(http.Client()),
builder: (context, snapshot){
if (snapshot.hasData)
//return Text("${snapshot.data!}");
return ListView.builder(
//itemCount: snapshot.data!.length,
itemBuilder: (context, index){
return Text("${snapshot.data!}");
});
else
return CircularProgressIndicator();
},
),
)
),
),
);
}
}
The json is hosted on localhost, from which I can successfully pull the json. Here is the class used for fetching the json from local host
class LiteratureService {
LiteratureDataModel literatureFromJson(String literature) {
//print(literature);
return LiteratureDataModel.fromJson(json.decode(literature));
}
String literatureToJson(LiteratureDataModel literatureDataModel) => json.encode(literatureDataModel.toJson());
Future fetchLiterature(http.Client client) async {
final response = await client.get(Uri.parse("http://localhost_ip_address:8000/literature/ultliterature.json"));
//print("Http response: ${response.body}");
return literatureFromJson(response.body);
}
}
I referred to the following link to solve the problem, but could not solve it:
*SOLVED* Use json data stored in class in future builder
In the above link, the OP faced a similar issue as I did. I followed the changes recommended in the correct answer but realized its just another way of creating factory constructor that is there in LiteratureDataModel class. Moreover, I still could not get the length of the data snapshot.
I referred to the below link as well, which shows different ways of JSON serialization and deserialization as well, and still could not solve the problem.
What am I doing wrong in my code? Any advice on needed corrections to my code will be helpful.
I solved the problem by omitting the LiteratureDataModel
class and changing the fetchLiterature()
function in the following way:
Future<List<LiteratureModel>> fetchLiterature(http.Client client) async {
final response =
await client.get(Uri.parse("http://localhost_ip_address:8000/literature/literature.json"));
List<LiteratureModel> literatureModel = List<LiteratureModel>.from(
json.decode(response.body)["data"].map((data) => LiteratureModel.fromJson(data)).toList());
return literatureModel;
}
I also made the following changes to FutureBuilder using this link as a guide
builder: (context, AsyncSnapshot<List<LiteratureModel>> snapshot)
If anyone knows a better way of solving the question I posted, please let me know
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.