You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 18:44:56