使用DetailsResponseModel.fromJson解析JSON无返回的问题求助
Dart模型解析JSON失败的原因排查与解决
问题背景
调用DetailsResponseModel.fromJson(response)无法解析出有效结果,但直接用dynamic类型可以正常获取返回数据。该Model由QuickType生成,已尝试多种调整仍未解决。调试确认GET请求能正常返回目标JSON数据,也曾针对datetime字段排查,问题已持续3天。
相关代码与返回数据
DetailsResponseModel代码
// To parse this JSON data, do // // final detailsResponseModel = detailsResponseModelFromJson(jsonString); import 'dart:convert'; DetailsResponseModel detailsResponseModelFromJson(String str) => DetailsResponseModel.fromJson(json.decode(str)); String detailsResponseModelToJson(DetailsResponseModel data) => json.encode(data.toJson()); class DetailsResponseModel { DetailsResponseModel({ required this.pkId, required this.status, required this.dateBegin, this.dateEnd, required this.usersTotal, required this.usersActive, required this.moneyTotal, required this.moneyRest, required this.incomeRate, required this.chart, }); int pkId; String status; DateTime dateBegin; DateTime? dateEnd; int usersTotal; int usersActive; double moneyTotal; int moneyRest; double incomeRate; List<Chart> chart; factory DetailsResponseModel.fromJson(Map<String, dynamic> json) => DetailsResponseModel( pkId: json["pk_id"], status: json["status"], dateBegin: DateTime.parse(json["date_begin"]), dateEnd: json["date_end"] == null ? null : DateTime.parse(json["date_end"]), usersTotal: json["users_total"], usersActive: json["users_active"], moneyTotal: json["money_total"]?.toDouble(), moneyRest: json["money_rest"], incomeRate: json["income_rate"]?.toDouble(), chart: List<Chart>.from(json["chart"].map((x) => Chart.fromJson(x))), ); Map<String, dynamic> toJson() => { "pk_id": pkId, "status": status, "date_begin": dateBegin.toIso8601String(), "date_end": dateEnd?.toIso8601String(), "users_total": usersTotal, "users_active": usersActive, "money_total": moneyTotal, "money_rest": moneyRest, "income_rate": incomeRate, "chart": List<dynamic>.from(chart.map((x) => x.toJson())), }; } class Chart { Chart({ required this.datetime, required this.value, }); DateTime datetime; double value; factory Chart.fromJson(Map<String, dynamic> json) => Chart( datetime: DateTime.parse(json["datetime"]), value: json["value"]?.toDouble(), ); Map<String, dynamic> toJson() => { "datetime": datetime.toIso8601String(), "value": value, }; }
返回的JSON数据
{ "pk_id": 5, "status": "ACTIVE", "date_begin": "2023-03-25T00:00:00Z", "date_end": null, "users_total": 6, "users_active": 6, "money_total": 15.0, "money_rest": 13.0, "income_rate": 1.5, "chart": [ { "datetime": "2023-04-12T16:43:45Z", "value": 7.0 }, { "datetime": "2023-04-04T16:44:27Z", "value": 3.0 } ] }
DataSource代码
import 'dart:convert'; import 'package:injectable/injectable.dart'; import '../../../core/shared/http.dart'; import '../../models/response/details_by_id_response_model.dart'; abstract class DetailsByIdRemoteDataSource { Future<DetailsResponseModel> getDetailsById({required int scenario}); } @LazySingleton(as: DetailsByIdRemoteDataSource) class DetailsByIdRemoteDataSourceImpl implements DetailsByIdRemoteDataSource { final Http http; const DetailsByIdRemoteDataSourceImpl({ required this.http, }); @override Future<DetailsResponseModel> getDetailsById( {required int scenario}) async { final response = await http.get( '/scenarioinfo?scenario_id=$scenario&pk_id=3', ); return DetailsResponseModel.fromJson(response); } }
核心原因分析
类型不匹配(最可能的问题)
返回的JSON中money_rest字段值为13.0(double类型),但Model里moneyRest被定义为int类型。Dart不允许将double直接赋值给int变量,解析时会抛出类型转换异常,导致整个Model实例化失败。而dynamic类型会自动隐式转换,所以能正常取值。Http返回值类型不确定
需确认自定义Http工具类的get方法返回的是已解码的Map<String, dynamic>还是原始JSON字符串:- 如果是原始字符串,直接传入
fromJson会报错,需要先调用json.decode()转换为Map再解析。 - 若返回的是Map,问题就集中在类型不匹配上。
- 如果是原始字符串,直接传入
异常未被捕获
当前代码没有异常捕获逻辑,解析失败时无法看到具体错误信息,导致排查困难。
解决方案
1. 修正类型不匹配问题
有两种处理方式:
方式一:修改Model字段类型
将moneyRest的类型从int改为double:double moneyRest;同时更新构造函数和
toJson方法对应的字段类型。方式二:显式转换类型
在fromJson工厂方法中,将money_rest的值转换为int:moneyRest: json["money_rest"].toInt(),
2. 验证Http返回值类型
检查Http类的get方法实现,如果返回的是String,修改DataSource代码:
@override Future<DetailsResponseModel> getDetailsById({required int scenario}) async { final responseStr = await http.get( '/scenarioinfo?scenario_id=$scenario&pk_id=3', ); final response = json.decode(responseStr) as Map<String, dynamic>; return DetailsResponseModel.fromJson(response); }
3. 添加异常捕获方便调试
在解析代码中加入try-catch,打印错误信息:
@override Future<DetailsResponseModel> getDetailsById({required int scenario}) async { final response = await http.get( '/scenarioinfo?scenario_id=$scenario&pk_id=3', ); try { return DetailsResponseModel.fromJson(response); } catch (e, stackTrace) { print('JSON解析错误详情: $e'); print('调用栈: $stackTrace'); rethrow; // 重新抛出异常不影响上层逻辑 } }
内容的提问来源于stack exchange,提问作者Murray Karelin
相关产品推荐
相关产品推荐

