Flutter POST请求解析嵌套JSON无数据显示问题求助
我看了你的代码和API返回结构,发现几个关键问题导致ListView无法显示数据,咱们一步步来修复:
问题分析与修复方案
1. 数据模型(Model)结构错误
你的API返回中result是一个数组(List),但你的TicketModel把result定义成了单个ResultTicket对象,这直接导致解析失败。另外还有字段类型不匹配和拼写错误:
- API里
id、ticket等字段是字符串(比如"id": "1"),但你Model里定义成了int类型 ccs是布尔值(false),你定义成了StringResultTicket.fromJson里有拼写错误:depatmentid→ 应该是departmentid
修正后的Model代码:
class TicketResponse { // 重命名更清晰,代表整个响应体 final int status; final String statusMessage; final List<ResultTicket> results; // 改成List类型,命名更语义化 TicketResponse({required this.status, required this.statusMessage, required this.results}); factory TicketResponse.fromJson(Map<String, dynamic> json) { // 解析result数组为ResultTicket列表 var resultsList = json['result'] as List; List<ResultTicket> resultItems = resultsList.map((item) => ResultTicket.fromJson(item)).toList(); return TicketResponse( status: json['status'], statusMessage: json['status_message'], results: resultItems, ); } } class ResultTicket{ final String id; // 改为String匹配API返回类型 final String ticket; final String departmentid; final String clientid; final String userid; final String adminid; final String assetid; final String projectid; final String email; final String subject; final String status; final String priority; final String timestamp; final String notes; final bool ccs; // 改为bool类型 final String timespent; ResultTicket({ required this.id, required this.ticket, required this.departmentid, required this.clientid, required this.userid, required this.adminid, required this.assetid, required this.projectid, required this.email, required this.subject, required this.status, required this.priority, required this.timestamp, required this.notes, required this.ccs, required this.timespent, }); factory ResultTicket.fromJson(Map<String, dynamic> json) { return ResultTicket( id: json['id'], ticket: json['ticket'], departmentid: json['departmentid'], // 修正拼写错误 clientid: json['clientid'], userid: json['userid'], adminid: json['adminid'], assetid: json['assetid'], projectid: json['projectid'], email: json['email'], subject: json['subject'], status: json['status'], priority: json['priority'], timestamp: json['timestamp'], notes: json['notes'], ccs: json['ccs'], // 直接读取布尔值 timespent: json['timespent'], ); } }
2. 数据获取与解析逻辑错误
你原来的_fetchData里,遍历的是整个data对象(包含status、status_message、result的根对象),而不是data['result']这个数组。另外,列表变量应该存储ResultTicket实例,而非TicketModel。
修正后的_fetchData和变量定义:
class _ReportState extends State<Report> { List<ResultTicket> _ticketList = []; // 改为存储ResultTicket的列表 var loading = false; Future<Null> _fetchData() async{ setState(() { loading = true; }); try { final response = await http.post( Uri.parse("http://192.168.43.253/edc/api/index.php"), // 用Uri.parse更规范 body: { 'key' : '5fpqRt23yU2kgJcl7fDo6ARIzsU5zIGAOIYtNPDBNokQcRViNfKnbaSiNow61lXG', 'method' : 'get', 'resource' : 'tickets', }, ); if (response.statusCode == 200) { final data = jsonDecode(response.body); // 解析整个响应对象 TicketResponse ticketResponse = TicketResponse.fromJson(data); setState(() { _ticketList = ticketResponse.results; // 直接赋值结果列表 loading = false; }); } else { throw Exception("请求状态码异常"); } } catch (e) { setState(() { loading = false; }); // 提示用户请求失败 ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("数据加载失败: ${e.toString()}")), ); } } @override void initState() { super.initState(); _fetchData(); } // ... 其余代码
3. ListView UI层修正
现在_ticketList是ResultTicket的列表,直接遍历即可,不需要通过x.result访问:
@override Widget build(BuildContext context) { return Scaffold( body: Container( child: loading ? const Center(child: CircularProgressIndicator()) : ListView.builder( itemCount: _ticketList.length, itemBuilder: (context, index){ final ticket = _ticketList[index]; return Container( padding: const EdgeInsets.all(10.0), margin: const EdgeInsets.symmetric(vertical: 4, horizontal: 8), decoration: BoxDecoration( border: Border.all(color: Colors.grey.shade300), borderRadius: BorderRadius.circular(8), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text("工单编号: ${ticket.ticket}", style: const TextStyle(fontWeight: FontWeight.bold)), const SizedBox(height: 4), Text("邮箱: ${ticket.email}"), Text("主题: ${ticket.subject}"), Text("状态: ${ticket.status}"), ], ), ); }, ), ), ); }
额外建议
- 用
try-catch包裹网络请求,处理网络异常、解析异常等情况,避免App崩溃 - 可以考虑用
FutureBuilder替代手动管理loading状态,代码会更简洁 - 字段命名遵循Dart小驼峰规范(比如
statusMessage替代status_message),提升代码可读性
内容的提问来源于stack exchange,提问作者Zakario Lesrahmanto
相关产品推荐
相关产品推荐

