Flutter json_serializable反序列化报Null非String子类型错误
你碰到的_TypeError (type 'Null' is not a subtype of type 'String')错误,核心原因是接口返回的JSON数据里存在字段值为null的情况,但你定义的所有实体类字段全是非空类型,json_serializable自动生成的强转逻辑遇到null值时会直接抛出类型转换异常。
常用的公开国家信息接口里,capital(部分无固定首都的小国)、gini(无基尼系数统计的国家)、borders(无陆地邻国的岛国)、cioc、numericCode,还有嵌套类里的货币符号、小语种翻译、区域组织字段都有可能返回null,你当前的代码强制要求所有字段必须是非空的String/int/List/自定义对象,自然会触发报错。
方案1:将可能为null的字段改为可空类型(适配真实接口返回,最稳妥)
给所有可能返回null的字段类型前加?标记为可空类型,同时去掉构造函数里这些字段的required关键字,修改完成后重新执行代码生成命令:
flutter pub run build_runner build --delete-conflicting-outputs
以Country类为例,修改后的参考代码:
@JsonSerializable() class Country { final String name; final List<String>? topLevelDomain; final String alpha2Code; final String alpha3Code; final List<String>? callingCodes; final String? capital; final List<String>? altSpellings; final String region; final String? continent; final int population; final List<int>? latlng; final String? demonym; final int? area; final double? gini; final List<String>? timezones; final List<String>? borders; final String? nativeName; final String? numericCode; final List<Currencies>? currencies; final List<Languages>? languages; final Translations? translations; final List<String>? flags; final List<RegionalBlocs>? regionalBlocs; final String? cioc; final bool? independent; Country( {required this.name, this.topLevelDomain, required this.alpha2Code, required this.alpha3Code, this.callingCodes, this.capital, this.altSpellings, required this.region, this.continent, required this.population, this.latlng, this.demonym, this.area, this.gini, this.timezones, this.borders, this.nativeName, this.numericCode, this.currencies, this.languages, this.translations, this.flags, this.regionalBlocs, this.cioc, this.independent}); factory Country.fromJson(Map<String, dynamic> json) => _$CountryFromJson(json); Map<String, dynamic> toJson() => _$CountryToJson(this); }
嵌套的Currencies、Languages、Translations、RegionalBlocs类按照同样规则修改即可,比如Currencies里的symbol字段部分小众货币没有对应符号会返回null,Translations里部分小语种翻译缺失也会返回null,都需要加可空标记。
方案2:给字段配置默认值,不使用可空类型
如果你不想在业务代码里处理空判断,可以用@JsonKey注解给可能为null的字段设置默认值,这样即使接口返回null,json_serializable会自动用默认值填充,不会抛类型错误:
// 示例:字符串类型字段默认空字符串,数组类型字段默认空数组 @JsonKey(defaultValue: '') final String capital; @JsonKey(defaultValue: []) final List<String> borders; @JsonKey(defaultValue: 0.0) final double gini;
快速定位null字段技巧
如果不确定具体是哪个字段返回null,可以在异常抛出的代码行打debug断点,运行到断点时查看当前正在转换的JSON map里哪个key对应的value是null,优先修改对应字段即可。
内容的提问来源于stack exchange,提问作者Sledge BOUNDA

