含Firestore Timestamp的Dart对象JSON编码报错求助
解决go_router传递含Firestore Timestamp对象的序列化错误
问题原因
go_router在传递extra参数时会对其进行JSON序列化,但Firestore的Timestamp类默认没有实现toJson()方法,导致序列化失败抛出错误。
解决方案
方法1:提前转换Timestamp为可序列化类型
在传递对象前,把Map里的Timestamp转成DateTime或毫秒数(int),这两种类型都能被JSON正常序列化。
示例代码:// 转换原数据中的Timestamp为DateTime final processedData = originalData.map((key, item) { return MapEntry( key, { 'date': item['date'].toDate(), // 调用Timestamp的toDate()方法转换 'meet': item['meet'], }, ); }); // 传递给go_router context.go('/your-target-page', extra: processedData);如果后续需要还原成
Timestamp,可以用Timestamp.fromDate(dateTimeObject)。方法2:给Timestamp添加序列化扩展
给Timestamp类写扩展方法,实现toJson和fromJson,让序列化框架能识别它:extension TimestampSerializer on Timestamp { Map<String, dynamic> toJson() { return {'seconds': seconds, 'nanoseconds': nanoseconds}; } static Timestamp fromJson(Map<String, dynamic> json) { return Timestamp(json['seconds'], json['nanoseconds']); } }要是你用
json_serializable生成自定义对象的序列化代码,记得在字段上指定转换器:@JsonSerializable() class MeetingRecord { @JsonKey( fromJson: TimestampSerializer.fromJson, toJson: TimestampSerializer.toJson ) final Timestamp date; final bool meet; MeetingRecord({required this.date, required this.meet}); factory MeetingRecord.fromJson(Map<String, dynamic> json) => _$MeetingRecordFromJson(json); Map<String, dynamic> toJson() => _$MeetingRecordToJson(this); }方法3:配置go_router自定义序列化器
初始化GoRouter时,自定义serializer来处理Timestamp的序列化和反序列化:final appRouter = GoRouter( serializer: GoRouterSerializer( write: (dynamic extra) { if (extra is Map<String, dynamic>) { // 遍历处理每个条目里的Timestamp final encodedMap = extra.map((key, value) { if (value is Map && value['date'] is Timestamp) { final ts = value['date'] as Timestamp; return MapEntry( key, { 'date': {'seconds': ts.seconds, 'nanoseconds': ts.nanoseconds}, 'meet': value['meet'], }, ); } return MapEntry(key, value); }); return jsonEncode(encodedMap); } return jsonEncode(extra); }, read: (String? encoded) { if (encoded == null) return null; final decodedMap = jsonDecode(encoded) as Map<String, dynamic>; // 反序列化还原Timestamp return decodedMap.map((key, value) { if (value is Map && value.containsKey('seconds')) { return MapEntry( key, { 'date': Timestamp(value['seconds'], value['nanoseconds']), 'meet': value['meet'], }, ); } return MapEntry(key, value); }); }, ), routes: [ // 你的路由配置 ], );
内容的提问来源于stack exchange,提问作者craig_ck
相关产品推荐
相关产品推荐

