Flutter调用API遇Error 400,求助JSON解析与数据展示问题
Flutter HTTP请求Error 400排查与公交数据解析方案
问题概述
此前可正常从指定URL获取公交站点数据,修改代码后触发Error 400 Bad Request,已确认URL本身无问题,需解决请求错误并实现公交线路号、绝对到达时间、相对到达时间的JSON解析与展示。
完整代码示例
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; // 公交到站数据模型 class BusArrival { final String routeNumber; final String absoluteTime; final String relativeTime; BusArrival({ required this.routeNumber, required this.absoluteTime, required this.relativeTime, }); // JSON转模型,添加空值容错 factory BusArrival.fromJson(Map<String, dynamic> json) { return BusArrival( routeNumber: json['route_number'] ?? '未知线路', absoluteTime: json['absolute_arrival_time'] ?? '无数据', relativeTime: json['relative_arrival_time'] ?? '无数据', ); } } class BusInfoPage extends StatefulWidget { const BusInfoPage({super.key}); @override State<BusInfoPage> createState() => _BusInfoPageState(); } class _BusInfoPageState extends State<BusInfoPage> { List<BusArrival> _busList = []; String _errorMsg = ''; // 请求公交数据核心方法 Future<void> fetchBusData() async { const targetUrl = '你的指定公交API URL'; // 已确认无问题的URL try { final response = await http.get(Uri.parse(targetUrl)); if (response.statusCode == 200) { final List<dynamic> rawData = jsonDecode(response.body); setState(() { _busList = rawData.map((item) => BusArrival.fromJson(item)).toList(); _errorMsg = ''; }); } else { setState(() { _errorMsg = '请求失败:Error ${response.statusCode}'; }); throw Exception('HTTP Error: ${response.statusCode}'); } } catch (e) { setState(() { _errorMsg = '请求异常:$e'; }); } } @override void initState() { super.initState(); fetchBusData(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('公交到站提醒')), body: Padding( padding: const EdgeInsets.all(16.0), child: _errorMsg.isNotEmpty ? Center(child: Text(_errorMsg, style: const TextStyle(color: Colors.red, fontSize: 16))) : ListView.builder( itemCount: _busList.length, itemBuilder: (context, index) { final bus = _busList[index]; return Card( margin: const EdgeInsets.symmetric(vertical: 8), child: Padding( padding: const EdgeInsets.all(12.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('线路号:${bus.routeNumber}', style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), const SizedBox(height: 8), Text('绝对到站时间:${bus.absoluteTime}'), Text('相对到站时间:${bus.relativeTime}'), ], ), ), ); }, ), ), floatingActionButton: FloatingActionButton( onPressed: fetchBusData, child: const Icon(Icons.refresh), ), ); } } void main() { runApp(const MaterialApp(home: BusInfoPage())); }
API返回示例
[ { "route_number": "101", "absolute_arrival_time": "2024-05-20 14:35:00", "relative_arrival_time": "5分钟后" }, { "route_number": "302", "absolute_arrival_time": "2024-05-20 14:38:00", "relative_arrival_time": "8分钟后" } ]
报错情况
- 触发时机:修改代码后执行HTTP GET请求时
- 错误内容:
Error 400 Bad Request - 已确认项:API URL本身有效,此前可正常获取数据
Error 400排查方向
- 检查请求头变更:若新增/修改了请求头(如
Content-Type、Authorization),确认是否符合API要求。GET请求通常无需设置Content-Type,误加可能导致400。 - 检查参数拼接:若修改了URL查询参数,确认参数格式、编码是否正确,是否存在未转义的特殊字符(如空格、中文)。
- 检查请求方法:是否误将GET改为POST,而目标API仅支持GET请求?
- 核对API规范:即使URL不变,API可能更新了请求规则(如新增必填参数),需对比原始可正常请求的参数/头信息。
- 直接测试请求:用curl或Postman直接请求目标URL,确认返回结果,再与代码中的请求做对比:
curl "你的指定公交API URL"
解析逻辑说明
- 定义
BusArrival模型类,与API返回字段一一映射,通过fromJson工厂方法实现JSON到模型的转换,添加空值默认值避免解析崩溃。 - 通过
http.get发起请求,成功后解析JSON数组,将每个元素转换为模型对象,再更新UI列表展示。
内容的提问来源于stack exchange,提问作者katamykenji
相关产品推荐
相关产品推荐

