如何修复@JsonSerializable中@JsonKey对象为Null的类型转换异常
解决Flutter中@JsonSerializable处理Null字段的序列化异常
问题原因
你的代码中shareInfo被定义为非空的ShareInfo类型,但当接口返回该字段为null时,自动生成的序列化代码会尝试将null强制转换为Map<String, dynamic>,触发type 'Null' is not a subtype of type 'Map<String, dynamic>'异常。
修复方法
方法1:将字段改为可空类型(推荐)
允许shareInfo为null,修改实体类字段类型为可空,让生成的代码自动处理null值:
import 'package:json_annotation/json_annotation.dart'; part 'jump.g.dart'; @JsonSerializable() class Jump extends Object { @JsonKey(name: 'des', defaultValue: '') String des; @JsonKey(name: 'shareInfo') ShareInfo? shareInfo; // 改为可空类型 Jump(this.des, this.shareInfo); factory Jump.fromJson(Map<String, dynamic> srcJson) => _$JumpFromJson(srcJson); Map<String, dynamic> toJson() => _$JumpToJson(this); }
执行代码生成命令(flutter pub run build_runner build)后,生成的_$JumpFromJson会自动处理null:
Jump _$JumpFromJson(Map<String, dynamic> json) { return Jump( json['des'] as String? ?? '', json['shareInfo'] == null ? null : ShareInfo.fromJson(json['shareInfo'] as Map<String, dynamic>), ); }
方法2:设置默认实例(要求字段非空时使用)
如果业务要求shareInfo不能为null,可以给字段设置默认实例,前提是ShareInfo有默认构造函数:
- 给
ShareInfo添加默认构造:
@JsonSerializable() class ShareInfo { String? title; // 其他字段... ShareInfo({this.title}); // 空实例构造函数 ShareInfo.empty() : title = ''; factory ShareInfo.fromJson(Map<String, dynamic> json) => _$ShareInfoFromJson(json); }
- 修改
Jump类的shareInfo字段注解:
@JsonSerializable() class Jump extends Object { @JsonKey(name: 'des', defaultValue: '') String des; @JsonKey(name: 'shareInfo', defaultValue: ShareInfo.empty()) // 设置默认实例 ShareInfo shareInfo; // 保持非空 Jump(this.des, this.shareInfo); factory Jump.fromJson(Map<String, dynamic> srcJson) => _$JumpFromJson(srcJson); Map<String, dynamic> toJson() => _$JumpToJson(this); }
重新生成代码后,当shareInfo为null时会自动使用ShareInfo.empty()实例,避免类型转换错误。
方法3:临时手动修改生成代码(不推荐)
如果不想重新生成代码,可临时修改jump.g.dart中的逻辑,但注意重新生成代码会覆盖此修改:
Jump _$JumpFromJson(Map<String, dynamic> json) { return Jump( json['des'] as String? ?? '', // 手动添加null判断 json['shareInfo'] != null ? ShareInfo.fromJson(json['shareInfo'] as Map<String, dynamic>) : ShareInfo.empty(), // 或者null(如果字段是可空类型) ); }
内容的提问来源于stack exchange,提问作者James2020
相关产品推荐
相关产品推荐

