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

如何在Firestore中自定义存储Timestamp类型数据

解决方案:将DateTime以Firestore原生Timestamp对象存储(配合Freezed)

问题根源

当前通过Freezed自动生成的toJson()方法序列化时,Firestore的Timestamp对象会被转成包含_seconds和_nanoseconds的普通Map,导致Firestore无法识别为原生Timestamp类型,最终存储为整数或Map结构。

修复步骤

1. 给DTO添加Firestore适配方法

不要依赖toJson()生成写入Firestore的Map,手动实现toFirestore()方法,直接传递原始Timestamp对象:

@freezed
abstract class OrderDataDto implements _$OrderDataDto {
  const OrderDataDto._();

  const factory OrderDataDto({
    required String uid,
    @TimestampConverter() required Timestamp orderDate,
  }) = _OrderDataDto;

  // 保留原有其他方法:fromDomain、toDomain、fromJson、fromFirestore

  // 新增:生成Firestore可识别的Map
  Map<String, dynamic> toFirestore() {
    return {
      'orderDate': orderDate, // 直接传入Timestamp对象,Firestore会识别为原生类型
      // 其他需要存储的字段按此方式添加
    };
  }
}

2. 修改写入Firestore的逻辑

使用toFirestore()返回的Map替代toJson():

// 示例写入代码
final orderDto = OrderDataDto.fromDomain(order);
await FirebaseFirestore.instance
    .collection('orders')
    .doc(orderDto.uid)
    .set(orderDto.toFirestore());

3. 优化TimestampConverter(可选)

如果需要兼容多场景序列化,调整转换器确保读取时能正确解析Firestore返回的Timestamp:

class TimestampConverter implements JsonConverter<Timestamp, dynamic> {
  const TimestampConverter();

  @override
  Timestamp fromJson(dynamic json) {
    if (json is Timestamp) {
      return json;
    }
    // 兼容整数毫秒时间戳(可选,按需添加)
    if (json is int) {
      return Timestamp.fromMillisecondsSinceEpoch(json);
    }
    throw FormatException('无法解析Timestamp: $json');
  }

  @override
  dynamic toJson(Timestamp timestamp) => timestamp;
}

效果验证

写入后,Firestore控制台中orderDate字段会显示为带时钟图标的原生Timestamp对象,而非整数或字符串。读取时,fromFirestore()方法可正确将Timestamp转换回DTO类型,再映射到Domain层的DateTime。

内容的提问来源于stack exchange,提问作者RominHood

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 21:05:21