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

Flutter解析非数组JSON对象(Map String)时返回值为空问题求助

解决Flutter解析JSON返回空列表的问题

嘿,别着急,我帮你看看问题出在哪!你卡了两周肯定急坏了,咱们一步步来排查修复~

问题根源分析

你的代码里有几个关键错误,导致解析后得到空列表:

  1. JSON层级处理错误
    你的接口返回的JSON外层是一个包含success字段的对象,真正的历史数据数组在success里面,但你直接用整个jsonItems去做map操作,而且map的时候还把整个jsonItems传给了fromJson,这完全不对。

  2. DateTime解析的潜在崩溃
    你的第二条数据里tkh_lawatan是"2020-12-21"(只有日期没有时分秒),直接用DateTime.parse会抛出异常,而你的catch块是空的,根本看不到这个错误,导致解析中断,最终返回空列表。

  3. 错误捕获太笼统
    你的catch (e)块什么都没做,出了错误也无法定位,这是调试的大忌。


修改后的代码

1. 修复HistoryService的getHistory方法

class HistoryService {
  Future<List<HistoryModel>> getHistory() async {
    // 先初始化空列表,避免返回null导致UI报错
    List<HistoryModel> historys = [];
    final prefs = await SharedPreferences.getInstance();
    final extractedUserData = json.decode(prefs.getString('userData')) as Map<String, Object>;
    var token = extractedUserData['token'];
    final url = apiURL + '/historyUser';
    
    try {
      var jsonResponse = await http.get(
        Uri.encodeFull(url), 
        headers: {"Authorization": "Bearer $token"}
      );
      
      print("请求状态码: ${jsonResponse.statusCode}");
      if (jsonResponse.statusCode == 200) {
        print("响应内容: ${jsonResponse.body}");
        final jsonItems = json.decode(jsonResponse.body);
        
        // 重点:先取出success字段对应的数组
        final successData = jsonItems['success'] as List;
        // 遍历数组,每个item单独传给fromJson
        historys = successData
            .map<HistoryModel>((jsonItem) => HistoryModel.fromJson(jsonItem))
            .toList();
        
        print("解析成功,共${historys.length}条数据");
      } else {
        print("请求失败,状态码: ${jsonResponse.statusCode}");
      }
    } catch (e) {
      // 打印错误信息,方便定位问题
      print("解析或请求出错: $e");
    }
    
    return historys;
  }
}

2. 修复HistoryModel的fromJson方法(处理DateTime解析)

class HistoryModel {
  final int idlawatan;
  final int slug;
  final int tujuan;
  final DateTime tkhLawatan;

  HistoryModel({required this.idlawatan, required this.slug, required this.tujuan, required this.tkhLawatan});

  factory HistoryModel.fromJson(Map<String,dynamic> json) {
    DateTime tkhLawatan;
    final dateString = json['tkh_lawatan'] as String;
    
    // 处理只有日期没有时间的情况
    if (dateString.length == 10) {
      // 补全时分秒为00:00:00
      tkhLawatan = DateTime.parse("$dateString 00:00:00");
    } else {
      tkhLawatan = DateTime.parse(dateString);
    }
    
    // 更安全的方式可以用tryParse,避免格式错误崩溃:
    // tkhLawatan = DateTime.tryParse(dateString) ?? DateTime.now();
    
    return HistoryModel(
      idlawatan: json['id_lawatan'] as int,
      slug: json['id_lokasi'] as int,
      tujuan: json['id_tujuan'] as int,
      tkhLawatan: tkhLawatan,
    );
  }
}

额外提示

  • 我给Model的构造函数加了required关键字,这是Flutter空安全的要求(如果你的项目开启了空安全的话),如果没开可以去掉。
  • 现在每次请求和解析都会打印关键信息,方便你后续调试。
  • 以后遇到类似问题,一定要在catch块里打印错误,这能帮你快速定位问题!

内容的提问来源于stack exchange,提问作者safwan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:24:49