如何从Firestore FieldValue中获取日期值?解决类型转换报错
问题分析与解决方案
问题根源
- 转换器逻辑错误:你的
ServerTimestampConverter在读取Firestore文档时,不管输入的json实际是Timestamp类型,都强制返回FieldValue.serverTimestamp(),导致类型不匹配报错。 - DTO字段类型不兼容:写入时用
FieldValue标记服务器时间,但读取时Firestore返回的是Timestamp,单一的FieldValue类型无法同时兼容写入标记和读取结果两种场景。
解决方案
1. 修正ServerTimestampConverter实现
让转换器在读取文档时返回Firestore实际存储的Timestamp,在写入文档时返回FieldValue.serverTimestamp(),适配两种场景:
class ServerTimestampConverter implements JsonConverter<Timestamp, Object> { const ServerTimestampConverter(); @override Timestamp fromJson(Object json) { // 读取时直接返回Firestore的Timestamp类型 return json as Timestamp; } @override Object toJson(Timestamp timestamp) { // 写入时返回服务器时间戳标记,让Firestore自动生成时间 return FieldValue.serverTimestamp(); } }
2. 调整DTO字段类型与转换逻辑
将creationTimestamp的类型改为Timestamp,读取时直接拿到Firestore返回的时间戳,写入时转换器自动替换为服务器时间标记:
@freezed abstract class KeekzCardDto implements _$KeekzCardDto { const factory KeekzCardDto({ required String keekzDescription, @ServerTimestampConverter() required Timestamp creationTimestamp, required String keekzCaption, required bool freeOfCharge, required bool handicapAccessible, required AddressDto address, }) = _KeekzCardDto; //! To Domain Models KeekzCard toDomain() { return KeekzCard( freeOfCharge: freeOfCharge, handicapAccessible: handicapAccessible, address: address.toDomain(), caption: KeekzCardCaption(keekzCaption), description: KeekzCardDescription(keekzDescription), creationTimeStamp: DateTimeStamp( creationTimestamp.toDate().toString(), ), ); } }
3. 写入文档的正确姿势
创建DTO实例时,creationTimestamp可以传任意临时Timestamp(比如Timestamp.now()),转换器会自动在写入时替换为Firestore服务器时间标记:
// 示例:创建DTO并写入Firestore final dto = KeekzCardDto( keekzDescription: "示例描述", creationTimestamp: Timestamp.now(), // 该值会被转换器自动替换 keekzCaption: "示例标题", freeOfCharge: true, handicapAccessible: false, address: AddressDto(...), ); FirebaseFirestore.instance.collection("cards").add(dto.toJson());
额外优化(可选)
如果想让业务层直接使用DateTime而非Timestamp,可以修改转换器直接处理DateTime与Firestore类型的转换:
class ServerTimestampConverter implements JsonConverter<DateTime, Object> { const ServerTimestampConverter(); @override DateTime fromJson(Object json) { return (json as Timestamp).toDate(); } @override Object toJson(DateTime date) { return FieldValue.serverTimestamp(); } }
对应的DTO字段改为required DateTime creationTimestamp,业务层转换逻辑也更简洁:
creationTimeStamp: DateTimeStamp(creationTimestamp.toString()),
内容的提问来源于stack exchange,提问作者SRel
相关产品推荐
相关产品推荐

