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

Flutter学习者求助:如何正确接收指定结构的JSON数据?

问题分析

你的代码无法解析JSON的核心原因是模型结构与接口返回的JSON格式不匹配,具体问题点:

  1. 接口返回的data是数组类型,你直接用result["data"]["sid"]取值会报错(数组不能通过字符串键访问);
  2. data数组中的单个对象里,假期明细存储在"0"、"1"这类数字索引键下,而非和name、use_day同级;
  3. 原UsedVacationsData模型没有对应JSON中的嵌套结构,导致字段映射失败。

解决方案

第一步:定义匹配JSON结构的模型类

根据接口返回格式,拆分出三个层级的模型:

// 单个假期明细的模型(对应"0"、"1"内的内容)
class UsedVacationItem {
  final String sid;
  final String period;
  final double cnt;

  UsedVacationItem({required this.sid, required this.period, required this.cnt});

  factory UsedVacationItem.fromJson(Map<String, dynamic> json) {
    return UsedVacationItem(
      sid: json['sid'],
      period: json['period'],
      cnt: json['cnt'].toDouble(),
    );
  }
}

// 用户假期汇总信息(对应data数组里的单个对象)
class UsedVacationUserInfo {
  final String name;
  final String imgUrl;
  final int useDay;
  final List<UsedVacationItem> vacationItems;

  UsedVacationUserInfo({
    required this.name,
    required this.imgUrl,
    required this.useDay,
    required this.vacationItems,
  });

  factory UsedVacationUserInfo.fromJson(Map<String, dynamic> json) {
    // 提取所有数字索引键对应的假期明细
    final List<UsedVacationItem> items = [];
    json.forEach((key, value) {
      if (int.tryParse(key) != null) {
        items.add(UsedVacationItem.fromJson(value));
      }
    });

    return UsedVacationUserInfo(
      name: json['name'],
      imgUrl: json['img_url'],
      useDay: json['use_day'],
      vacationItems: items,
    );
  }
}

// 整个接口返回的响应模型
class UsedVacationsResponse {
  final String result;
  final String message;
  final List<UsedVacationUserInfo> data;

  UsedVacationsResponse({
    required this.result,
    required this.message,
    required this.data,
  });

  factory UsedVacationsResponse.fromJson(Map<String, dynamic> json) {
    final List<UsedVacationUserInfo> dataList = (json['data'] as List)
        .map((item) => UsedVacationUserInfo.fromJson(item))
        .toList();

    return UsedVacationsResponse(
      result: json['result'],
      message: json['message'],
      data: dataList,
    );
  }
}

第二步:修改Repository层的解析代码

调整原方法,适配新的模型和JSON结构:

Future<UsedVacationsResponse> fetchUsedVacationsData(
    Map<String, dynamic> params) async {
  Dio dio = await authDio();
  final response = await dio.get(API.usevacation_list, queryParameters: params);

  // Dio默认会自动解析JSON,若response.data是字符串则手动解码
  final Map<String, dynamic> result = response.data is String 
      ? json.decode(response.data) 
      : response.data;

  try {
    return UsedVacationsResponse.fromJson(result);
  } catch (e) {
    print('解析错误详情:$e');
    rethrow; // 抛出异常让上层处理
  }
}

第三步:调用示例

在业务层调用接口并处理数据:

void loadVacationData() async {
  try {
    final response = await yourRepository.fetchUsedVacationsData({'你的参数': '值'});
    if (response.result == 'SUCCESS') {
      // 取数组中第一个用户的假期信息(根据接口逻辑调整)
      final userInfo = response.data.first;
      print('用户名:${userInfo.name}');
      print('总休假天数:${userInfo.useDay}');
      
      // 遍历所有假期明细
      for (var item in userInfo.vacationItems) {
        print('休假日期:${item.period},天数:${item.cnt}');
      }
    } else {
      print('接口返回失败:${response.message}');
    }
  } catch (e) {
    print('请求失败:$e');
  }
}

注意事项
  1. 检查Dio配置:如果已设置responseType: ResponseType.json,则无需手动调用json.decode;
  2. 字段一致性:原代码中的img_rm字段在接口返回中不存在,需删除或确认接口是否遗漏该字段;
  3. 异常处理:建议在业务层捕获异常,展示友好的错误提示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 04:53:08