Kotlin读取Firebase Firestore自定义对象报ClassCastException问题
问题根因
Firestore客户端SDK读取文档数据时,默认会把嵌套对象解析为HashMap<String, Any?>结构,直接对列表字段做泛型强转时,由于JVM泛型擦除机制,编译阶段不会校验列表内的元素类型,运行时实际拿到的是MutableList<HashMap>,强转为MutableList<SelfMadeQuestion>就会抛出ClassCastException。
你的自定义类上传逻辑正常,是因为写入时SDK可以正确把自定义类序列化为Firestore支持的结构,和读取时的反序列化逻辑不互通。
解决方法
方案1:使用SDK内置的toObject方法自动映射(推荐)
这是最简便的实现方式,只要保证自定义类有无参构造(你的SelfMadeQuestion所有参数都带默认值,Kotlin会自动生成无参构造,满足要求),就可以直接让SDK完成全量字段映射:
// 定义和用户文档结构匹配的数据类,按需补充其他文档字段 data class UserDoc( val selfMadeQuestions: MutableList<SelfMadeQuestion> = mutableListOf() ) fStore.collection("users").get().addOnSuccessListener { documents -> for (doc in documents) { // 直接将整个文档映射为自定义对象,嵌套列表会自动完成类型转换 val userData = doc.toObject(UserDoc::class.java) val questionList = userData.selfMadeQuestions // 后续直接使用questionList即可,类型为MutableList<SelfMadeQuestion> } }
方案2:手动逐元素转换
如果不需要映射整个文档,只想单独提取selfMadeQuestions字段,可以先拿到原始的HashMap列表,逐个转换为目标对象:
fStore.collection("users").get().addOnSuccessListener { documents -> for (doc in documents) { // 先获取原始结构的列表 val rawQuestionList = doc.get("selfMadeQuestions") as? MutableList<Map<String, Any?>> ?: mutableListOf() val targetList = mutableListOf<SelfMadeQuestion>() for (rawItem in rawQuestionList) { val question = SelfMadeQuestion( openQuestion = rawItem["openQuestion"] as? Boolean ?: false, questionText = rawItem["questionText"] as? String ?: "", answers = rawItem["answers"] as? List<String> ?: mutableListOf(), rightAnswer = rawItem["rightAnswer"] as? String ?: "" ) targetList.add(question) } // targetList即为转换完成的目标类型列表 } }
注意事项
- 不要直接对带泛型的集合类型做强制类型转换,泛型擦除机制会导致类型校验滞后到运行时,触发类型转换异常
- 如果使用
toObject方法,自定义类必须保证存在无参构造,且字段名和Firestore中存储的字段名完全一致,否则会映射失败
内容的提问来源于stack exchange,提问作者Claudiu Felix
相关产品推荐
相关产品推荐

