Flutter学习者求助:如何正确接收指定结构的JSON数据?
问题分析
你的代码无法解析JSON的核心原因是模型结构与接口返回的JSON格式不匹配,具体问题点:
- 接口返回的
data是数组类型,你直接用result["data"]["sid"]取值会报错(数组不能通过字符串键访问); data数组中的单个对象里,假期明细存储在"0"、"1"这类数字索引键下,而非和name、use_day同级;- 原
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'); } }
注意事项
- 检查Dio配置:如果已设置
responseType: ResponseType.json,则无需手动调用json.decode; - 字段一致性:原代码中的
img_rm字段在接口返回中不存在,需删除或确认接口是否遗漏该字段; - 异常处理:建议在业务层捕获异常,展示友好的错误提示。
内容的提问来源于stack exchange,提问作者sopu5555
相关产品推荐
相关产品推荐

