从Java 8迁移至17,将POJO转为Record引发Firestore序列化错误
Java 17 Record与Firestore DocumentSnapshot.toObject() 报错解决方法
问题原因
你遇到的No properties to serialize found错误,是因为当前使用的google-cloud-firestore 3.14.0版本尚未原生支持Java 17的Record类型。Firestore默认序列化机制依赖POJO的getter/setter或可访问字段,而Record的组件通过无前缀的访问方法(如aString1())暴露,且本身是不可变类型,旧版SDK无法识别其结构。
解决方案
方案1:升级Firestore SDK到支持Record的版本
Google Cloud Firestore Java SDK在3.20.0及以上版本中添加了对Java Record的原生支持,升级后无需额外修改即可直接使用toObject(MyRecord.class)。
升级依赖示例(Maven)
修改pom.xml中的依赖版本:
<dependency> <groupId>com.google.cloud</groupId> <artifactId>google-cloud-firestore</artifactId> <version>3.20.0</version> <!-- 推荐使用最新稳定版 --> </dependency>
升级后,Firestore会自动识别Record的组件,调用其构造方法完成反序列化,同时也支持将Record写入Firestore。
方案2:自定义Firestore数据转换器(无法升级SDK时使用)
如果无法升级SDK,可以实现FirestoreDataConverter接口,手动处理Record与Firestore文档的转换逻辑。
自定义转换器代码
import com.google.cloud.firestore.QueryDocumentSnapshot; import com.google.cloud.firestore.FirestoreDataConverter; import java.util.List; import java.util.Map; public class MyRecordConverter implements FirestoreDataConverter<MyRecord> { @Override public MyRecord fromFirestore(QueryDocumentSnapshot snapshot) { Map<String, Object> data = snapshot.getData(); return new MyRecord( (String) data.get("aString1"), (String) data.get("aString2"), (String) data.get("aString3"), (String) data.get("aString4"), (String) data.get("aString5"), (String) data.get("aString6"), ((Number) data.get("anInt")).intValue(), (Map<String, List<String>>) data.get("services") ); } @Override public Map<String, Object> toFirestore(MyRecord record) { return Map.of( "aString1", record.aString1(), "aString2", record.aString2(), "aString3", record.aString3(), "aString4", record.aString4(), "aString5", record.aString5(), "aString6", record.aString6(), "anInt", record.anInt(), "services", record.services() ); } }
使用转换器替换toObject调用
DocumentSnapshot document = future.get(); if (document.exists()) { MyRecord myRecord = new MyRecordConverter().fromFirestore((QueryDocumentSnapshot) document); if (myRecord != null) { fetchData(myRecord); } return myRecord; }
额外注意事项
- 确保Record的组件名称与Firestore文档中的字段名完全一致,若需要映射不同名称的字段,可使用
@PropertyName注解(SDK支持后生效,或在转换器中手动处理字段名映射):public record MyRecord( @PropertyName("string_1") String aString1, // 其他字段... ) {}
内容的提问来源于stack exchange,提问作者JKawa
相关产品推荐
相关产品推荐

