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

Flutter中JSON转List异常:FutureBuilder+ListView展示HTTP数据求助

JSON转List及FutureBuilder展示问题排查与修复

尝试通过HTTP GET获取数据库列表数据,转换为List后用FutureBuilder+ListView展示,但JSON转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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 07:09:56