问题描述
我正在尝试将响应映射到模型类,然后一一显示所有元素,以便用户可以向下滚动。回复是这样的:
{"items":[{"id":"bd9acd37-5c91-47cb-a71e-0e43fb2f7882","imageUrl":"","title":"fak hez as","city":"Gdansk"},{"id":"210ad8c8-d279-4c38-845c-34c772cfec21","title":"Some random title :)","city":"Warsaw"}],"total":2,"pageNumber":1}
还有我用 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>{};
map["id"] = _id;
map["imageUrl"] = _imageUrl;
map["title"] = _title;
map["city"] = _city;
return map;
}
}
我的屏幕:
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');
}
}
}
执行此行时出错:
List<Advertisement> z = (json.decode(response.body) as List)
.map((i) => Advertisement.fromJson(i))
.toList();
它没有映射到这个列表
在调试时我得到:
我做错了什么?模型类有问题吗?
解决方法
您在代码中犯的另一个错误,您正在构建(BuildContext 上下文)中调用 fetchAdvertisement() 方法。这意味着每次调用 build() 方法。它也会调用 fetchAdvertisement() 这个。
Column( children: [ FutureBuilder( future: fetchAdvertisements(),builder: (context,snapshot) => snapshot.hasData ? Text("") : snapshot.hasError ? Text("An error occurred") : CircularProgressIndicator(),),],
为了避免这样的问题。
late Function _fetchAdvertisements; void initState() { super.initState(); _fetchAdvertisements = fetchAdvertisements(); }
Column( children: [ FutureBuilder( future: _fetchAdvertisements,,
您不能简单地使用强制转换 as List
来解析它。因为您的回复甚至不是列表。
{
"items": [
{
"id": "bd9acd37-5c91-47cb-a71e-0e43fb2f7882","imageUrl": "","title": "fak hez as","city": "Gdansk"
},{
"id": "210ad8c8-d279-4c38-845c-34c772cfec21","title": "Pozdrawiam z Łodzi :)","city": "Warsaw"
}
],"total": 2,"pageNumber": 1
}
对于这个响应,你可以这样解析:
Advertisement.fromJson(json.decode(response.body))
但现在您只有一项 Advertisement
。
如果你的回复是这样的,有多个广告:
{
"advertisements": [
{
"items": [
{
"id": "bd9acd37-5c91-47cb-a71e-0e43fb2f7882","city": "Gdansk"
},{
"id": "212ad8c8-d279-4c38-845c-34c772cfec21","title": "Great city!","city": "Łódź"
}
],"pageNumber": 1
},{
"items": [
{
"id": "bd9acd37-5c91-47cb-a71e-0e43fb2f7882",{
"id": "210ad8c8-d279-4c38-845c-34c772cfec21","title": "Some random title :)","city": "Warsaw"
}
],"pageNumber": 1
}
]
}
您可以使用以下代码简单地解析:
List<Advertisement> advertisements = [
for (final advertisement in json.decode(response2)['advertisements'])
Advertisement.fromJson(advertisement)
];
您可以使用 JsonSerializable
学习如何正确进行 JSON 序列化,我建议您阅读此 here。
我刚刚复制了您的 Respond.body 文本并向您展示了一个虚拟示例。一切都将以相同的方式完成,天气您使用 HTTP 调用。始终确保您知道会出现什么响应。
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","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());
}
}
未触及的物品.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;
}
}
未触及的广告.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>{};
if (_items != null) {
map["items"] = _items?.map((v) => v.toJson()).toList();
}
map["total"] = _total;
map["pageNumber"] = _pageNumber;
return map;
}
}
,
这是一张在每次构建时解析 fetchAdvertisements() 调用的图片