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

含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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 02:45:18