如何在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
相关产品推荐
相关产品推荐

