Flutter中JSON转List异常:FutureBuilder+ListView展示HTTP数据求助
JSON转List及FutureBuilder展示问题排查与修复
尝试通过HTTP GET获取数据库列表数据,转换为List
1. getData方法返回错误类型
问题:明明已经将JSON转换为List<Party>,但最终返回的是HTTP响应对象response,导致FutureBuilder拿到的不是Party列表。
修复:返回转换后的parties列表。
修正后的getData方法:
Future<List<Party>> getData() async { var response = await http.get( Uri.parse('http://10.0.2.2:8000/party/find'), headers: <String, String>{ 'Content-Type': 'application/x-www-form-urlencoded' }, ); if (response.statusCode == 200) { List<dynamic> jsonDataList = json.decode(response.body); List<Party> parties = jsonDataList.map((json) => Party.fromJson(json)).toList(); print(parties); return parties; // 返回转换后的Party列表 } else { print("请求失败"); return []; // 返回空列表避免崩溃 } }
2. Party.fromJson解析存在两个关键问题
2.1 party_member_id类型转换不安全
问题:JSON解析出的数组是List<dynamic>,直接强转List<String>会触发类型错误。
修复:用List<String>.from()显式转换。
2.2 部分JSON对象字段不匹配
问题:第一个JSON对象返回的是party_Lat、party_Lng,但Party类定义的是departure_party_Lat、departure_party_Lng等,解析时会找不到字段报错。
修复:兼容两种字段名,设置默认值避免崩溃。
修正后的Party.fromJson:
factory Party.fromJson(Map<String, dynamic> json) { return Party( json['date_time'] as String, json['destination'] as String, json['departure'] as String, json['max_recruitment'] as int, json['cur_recruitment'] as int, json['party_type'] as String, json['party_recruiter_id'] as String, List<String>.from(json['party_member_id']), // 安全转换数组类型 (json['departure_party_Lat'] ?? json['party_Lat'] ?? 0.0) as double, // 兼容字段 (json['departure_party_Lng'] ?? json['party_Lng'] ?? 0.0) as double, json['destination_party_Lat'] as double? ?? 0.0, json['destination_party_Lng'] as double? ?? 0.0, ); }
3. FutureBuilder与ListView的错误修复
3.1 拼写错误:legnth → length
3.2 访问不存在的字段:dateTime → date_time
3.3 状态字符串拼接错误:使用字符串插值而非字面量
3.4 完善状态处理:判断连接状态与错误情况
修正后的FutureBuilder代码:
FutureBuilder<List<Party>>( future: getData(), builder: (context, snapshot) { if (snapshot.connectionState != ConnectionState.done) { return CircularProgressIndicator(); } if (snapshot.hasError || snapshot.data == null) { return Text("加载失败"); } final parties = snapshot.data!; return ListView.builder( itemCount: parties.length, itemBuilder: (BuildContext context, int index) { final party = parties[index]; return Padding( padding: const EdgeInsets.all(8.0), child: card_partylist( party.date_time, party.party_type, party.date_time.split(' ').last, // 从date_time中提取时间部分 party.departure, party.destination, '${party.cur_recruitment}/${party.max_recruitment}' ), ); }, ); }, ),
补充说明
- 若后端能统一返回字段名(比如全部使用
departure_party_Lat而非混合party_Lat),可去掉兼容性代码,减少维护成本。 - 建议给Party类的构造函数参数添加命名参数,提高代码可读性,避免参数顺序错误。
内容的提问来源于stack exchange,提问作者Taetkyle
相关产品推荐
相关产品推荐

