You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,提问作者Мария Пелагейчева

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 04:49:57