Flutter中使用JSONSerializable映射JSON列表失败求助
Flutter JSONSerializable 映射JSON列表失败排查与修复
问题现象
调用API返回200状态码,但触发默认错误提示,说明JSON到实体的映射存在异常。
API返回响应
接口返回的JSON结构如下:
{ "code": 200, "message": "Countries Lists", "count": 250, "data": [ { "id": 1, "name": "Afghanistan" }, { "id": 2, "name": "Aland Islands" } // 其余国家数据省略 ] }
当前实体类代码
@JsonSerializable() class BaseResponse { @JsonKey(name: "code") int? status; @JsonKey(name: "message") String? message; } @JsonSerializable(explicitToJson: true) class AllCountryResponse extends BaseResponse { @JsonKey(name: "data") List<CountryResponse> data; AllCountryResponse(this.data); factory AllCountryResponse.fromJson(Map<String, dynamic> json) => _$AllCountryResponseFromJson(json); Map<String, dynamic> toJson() => _$AllCountryResponseToJson(this); } @JsonSerializable() class CountryResponse { @JsonKey(name: "id") String? id; @JsonKey(name: "name") String? name; CountryResponse(this.id, this.name); factory CountryResponse.fromJson(Map<String, dynamic> json) => _$CountryResponseFromJson(json); Map<String, dynamic> toJson() => _$CountryResponseToJson(this); }
当前映射器代码
class Countries { String id,name; Countries(this.id,this.name); } class AllCountries{ List<Countries> countries; AllCountries(this.countries); } extension CountryResponseMapper on CountryResponse? { Countries toDomain() { return Countries( this?.id.orEmpty() ?? EMPTY, this?.name.orEmpty() ?? EMPTY); } } extension AllCountriesResponseMapper on AllCountryResponse? { AllCountries toDomain() { return AllCountries(this?.data.map((e) => e.toDomain()).toList() ?? []); } }
问题分析与修复方案
1. 数据类型不匹配
API返回的id是数字类型(int),但CountryResponse中定义的id为String?类型,JSONSerializable映射时会因类型不匹配抛出异常,直接导致映射失败。
修复:将CountryResponse的id类型改为int?,若业务需要String类型,在映射到领域模型时再转换:
@JsonSerializable() class CountryResponse { @JsonKey(name: "id") int? id; // 改为int类型匹配API返回 @JsonKey(name: "name") String? name; CountryResponse({this.id, this.name}); // 改用命名构造函数,避免位置参数问题 factory CountryResponse.fromJson(Map<String, dynamic> json) => _$CountryResponseFromJson(json); Map<String, dynamic> toJson() => _$CountryResponseToJson(this); }
2. 父类序列化逻辑缺失
AllCountryResponse继承自BaseResponse,但BaseResponse未配置序列化方法,JSONSerializable无法正确解析父类的code和message字段,可能引发序列化异常。
修复:给BaseResponse添加序列化方法,并在子类中正确继承父类字段:
@JsonSerializable() class BaseResponse { @JsonKey(name: "code") int? status; @JsonKey(name: "message") String? message; BaseResponse({this.status, this.message}); // 添加父类序列化方法 factory BaseResponse.fromJson(Map<String, dynamic> json) => _$BaseResponseFromJson(json); Map<String, dynamic> toJson() => _$BaseResponseToJson(this); } @JsonSerializable(explicitToJson: true) class AllCountryResponse extends BaseResponse { @JsonKey(name: "data") List<CountryResponse> data; AllCountryResponse({required this.data, super.status, super.message}); factory AllCountryResponse.fromJson(Map<String, dynamic> json) => _$AllCountryResponseFromJson(json); Map<String, dynamic> toJson() => _$AllCountryResponseToJson(this); }
3. 映射器空安全优化
映射器中this?.id.orEmpty() ?? EMPTY存在潜在风险:若orEmpty()未定义或EMPTY常量未声明,会触发错误。可直接替换为null判断逻辑:
extension CountryResponseMapper on CountryResponse? { Countries toDomain() { final response = this; return Countries( response?.id?.toString() ?? '', // 将int类型id转为String response?.name ?? '', ); } }
4. 处理未使用的count字段
API返回的count字段未在实体类中定义,若开启序列化严格模式会抛出异常。可在AllCountryResponse中添加忽略配置:
@JsonSerializable(explicitToJson: true) class AllCountryResponse extends BaseResponse { @JsonKey(name: "data") List<CountryResponse> data; @JsonKey(ignore: true) // 忽略count字段 int? count; AllCountryResponse({required this.data, super.status, super.message}); // ... 其余代码不变 }
最后操作
修改代码后,重新运行序列化代码生成命令:
flutter pub run build_runner build
重新测试API调用,确认映射正常,不再触发错误提示。
内容的提问来源于stack exchange,提问作者Ankit
相关产品推荐
相关产品推荐

