如何在Flutter中用JSONSerializable处理Cloud Firestore嵌套字段与Workout集合
解决Workout集合的嵌套与Map序列化问题
针对Workout集合的嵌套结构和Map类型字段,我们可以通过拆解嵌套为子模型+JSONSerializable的嵌套序列化支持来解决,具体步骤如下:
1. 拆解嵌套结构,定义子模型
根据Workout集合的嵌套层级,先定义两个子模型来处理深层数据:
1.1 训练组模型(WorkoutSet)
对应每个练习下的单组记录:
@JsonSerializable() class WorkoutSet { final double weight; final int reps; final bool completed; WorkoutSet({ required this.weight, required this.reps, required this.completed, }); factory WorkoutSet.fromJson(Map<String, dynamic> json) => _$WorkoutSetFromJson(json); Map<String, dynamic> toJson() => _$WorkoutSetToJson(this); }
1.2 训练项模型(WorkoutExercise)
对应Workout中关联的单个Exercise及其所有训练组数据:
@JsonSerializable() class WorkoutExercise { final List<WorkoutSet> sets; WorkoutExercise({required this.sets}); factory WorkoutExercise.fromJson(Map<String, dynamic> json) => _$WorkoutExerciseFromJson(json); Map<String, dynamic> toJson() => _$WorkoutExerciseToJson(this); }
2. 定义Workout主模型
处理Firestore Timestamp与Dart DateTime的转换,同时支持Map类型的exercises字段(键为exerciseId,值为对应训练项数据):
@JsonSerializable() class Workout { final String id; final String userId; final String name; // 自定义转换Firestore Timestamp和Dart DateTime @JsonKey(fromJson: _timestampToDateTime, toJson: _dateTimeToTimestamp) final DateTime date; // 动态键Map:键为exerciseId,值为WorkoutExercise实例 final Map<String, WorkoutExercise> exercises; Workout({ this.id = '', required this.userId, required this.name, required this.date, required this.exercises, }); // Timestamp转DateTime static DateTime _timestampToDateTime(Timestamp timestamp) { return timestamp.toDate(); } // DateTime转Timestamp static Timestamp _dateTimeToTimestamp(DateTime dateTime) { return Timestamp.fromDate(dateTime); } factory Workout.fromJson(Map<String, dynamic> json) => _$WorkoutFromJson(json); Map<String, dynamic> toJson() => _$WorkoutToJson(this); }
3. 生成序列化代码
在终端执行命令,自动生成对应的.g.dart文件:
flutter pub run build_runner build
关键注意事项
- 确保
pubspec.yaml已添加依赖:dependencies: flutter: sdk: flutter cloud_firestore: ^latest_version json_annotation: ^latest_version dev_dependencies: build_runner: ^latest_version json_serializable: ^latest_version - 若Workout集合还有其他嵌套字段,按相同逻辑拆解为子模型即可;
- 动态键Map(比如用户自定义的exerciseId)无需额外配置,
Map<String, T>类型原生支持JSONSerializable序列化; - 空安全适配:如果Firestore中存在可空字段,需给模型字段添加
?并在构造函数中设置默认值。
内容的提问来源于stack exchange,提问作者Leonard
相关产品推荐
相关产品推荐

