使用Dart json_serializable处理自定义属性序列化报错问题
解决Firestore自定义类型序列化错误:Invalid argument: Instance of 'HabitFrequency'
你的问题核心是嵌套自定义类、枚举及DateTime的序列化配置不全,导致json_serializable未生成正确的转换代码,Firestore无法识别HabitFrequency实例。以下是具体解决步骤:
1. 处理枚举的序列化
HabitFrequencyType作为枚举,默认不会被json_serializable自动序列化,需添加注解并生成转换代码:
@JsonEnum() enum HabitFrequencyType { daily, weekly, monthly // 你的其他枚举值 }
2. 适配Firestore的DateTime与Timestamp转换
Firestore存储日期用Timestamp类型,而非Dart原生DateTime,需自定义转换器:
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:json_annotation/json_annotation.dart'; class DateTimeToTimestampConverter implements JsonConverter<DateTime, Timestamp> { const DateTimeToTimestampConverter(); @override DateTime fromJson(Timestamp timestamp) => timestamp.toDate(); @override Timestamp toJson(DateTime date) => Timestamp.fromDate(date); }
将转换器应用到HabitCompletion的timestamp字段:
@JsonSerializable() class HabitCompletion { @JsonKey(converter: DateTimeToTimestampConverter()) DateTime timestamp; bool completion; String? stringValue; double? numericValue; HabitCompletion({ required this.timestamp, required this.completion, this.stringValue, this.numericValue, }); factory HabitCompletion.fromJson(Map<String, dynamic> json) => _$HabitCompletionFromJson(json); Map<String, dynamic> toJson() => _$HabitCompletionToJson(this); }
3. 重新生成序列化代码
执行build_runner命令,确保所有类的转换代码被正确生成(覆盖旧代码):
# Flutter项目 flutter pub run build_runner build --delete-conflicting-outputs # Dart项目 dart pub run build_runner build --delete-conflicting-outputs
4. 确保Firestore写入时传入序列化后的Map
保存Habit到Firestore时,必须传入toJson()返回的Map<String, dynamic>,而非直接传Habit实例:
// 正确写法 await FirebaseFirestore.instance .collection('habits') .doc(habit.id) .set(habit.toJson()); // 错误写法(会导致你遇到的报错) // await FirebaseFirestore.instance.collection('habits').doc(habit.id).set(habit);
完成以上步骤后,HabitFrequency会被正确序列化为Map,HabitCompletion列表会被序列化为Map数组,Firestore就能正常读写了。
内容的提问来源于stack exchange,提问作者Charlie Page
相关产品推荐
相关产品推荐

