JsonSerializable反序列化时如何基于同类其他字段赋值?
解决json_serializable多字段复用同一JSON键的冲突
问题描述
在使用Dart的json_serializable库时,若需要从同一个JSON键(示例中的"сommands")生成类的两个不同字段,直接给两个字段标记@JsonKey(name: 'сommands')会触发以下错误:
报错信息翻译:
"存在多个字段使用了JSON键'сommands'。"
场景需求:
Team类包含name和curator字段Project类需要从JSON的"сommands"数组生成teams(List<Team>)和curators(List<String>,提取每个Team的curator)- 原始JSON仅包含
"сommands"键,无"curators"字段
原始类定义
class Team { String name; String curator; // 其他字段 Team({required this.name, required this.curator}); } class Project { List<Team> teams; List<String> curators; // 其他字段 }
目标JSON数据
{ "сommands": [ { "name": "team 1", "curator": "curator 1" }, { "name": "team 2", "curator": "curator 2" } ] // 其他字段 }
触发错误的代码
@JsonSerializable(explicitToJson: true) class Project { @JsonKey(name: 'сommands', fromJson: curatorsFromJson) List<String> curators; @JsonKey(name: 'сommands') List<Team> currentTeams; // 其他字段 } List<String> curatorsFromJson(dynamic data) { // 提取curator的逻辑 }
可行解决方案
方案1:通过Getter推导curators字段
只让teams字段绑定JSON键,curators通过teams的getter自动推导,无需绑定JSON键:
@JsonSerializable(explicitToJson: true) class Project { @JsonKey(name: 'сommands') final List<Team> teams; // 通过teams自动生成curators列表 List<String> get curators => teams.map((team) => team.curator).toList(); Project({required this.teams}); factory Project.fromJson(Map<String, dynamic> json) => _$ProjectFromJson(json); Map<String, dynamic> toJson() => _$ProjectToJson(this); }
注意:如果需要将curators序列化到JSON输出中,需要给getter添加@JsonKey(includeToJson: true),或者手动在toJson方法中补充该字段。
方案2:自定义fromJson方法完全控制解析流程
手动编写fromJson方法,先解析teams,再从中提取curators,彻底避免键冲突:
@JsonSerializable(explicitToJson: true) class Project { final List<Team> teams; final List<String> curators; Project({required this.teams, required this.curators}); factory Project.fromJson(Map<String, dynamic> json) { // 解析teams列表 final List<Team> teams = (json['сommands'] as List) .map((item) => Team.fromJson(item as Map<String, dynamic>)) .toList(); // 从teams提取curators final List<String> curators = teams.map((team) => team.curator).toList(); return Project(teams: teams, curators: curators); } Map<String, dynamic> toJson() => _$ProjectToJson(this); }
这种方式灵活性最高,适合需要额外处理逻辑的场景。
方案3:标记curators为忽略字段,手动赋值
给curators添加@JsonKey(ignore: true),然后在自动生成的fromJson基础上手动补充curators的值:
@JsonSerializable(explicitToJson: true) class Project { @JsonKey(ignore: true) late List<String> curators; @JsonKey(name: 'сommands') final List<Team> teams; Project({required this.teams}); factory Project.fromJson(Map<String, dynamic> json) { final project = _$ProjectFromJson(json); // 手动设置curators project.curators = project.teams.map((team) => team.curator).toList(); return project; } Map<String, dynamic> toJson() => _$ProjectToJson(this); }
这种方式保留了自动生成的序列化代码,仅补充必要的逻辑。
内容的提问来源于stack exchange,提问作者Мария Пелагейчева
相关产品推荐
相关产品推荐

