无法反序列化 object.Can 无法将类型 java.lang.String 的对象转换为类型 com.example.quiz.models.Question(在字段 'questions.title' 中找到)

Could not deserialize object.Can't convert object of type java.lang.String to type com.example.quiz.models.Question (found in field 'questions.title')

我正在尝试从 Firestore 获取数据。但是出现错误:

java.lang.RuntimeException: Could not deserialize object. Can't convert object of type java.lang.String to type com.example.quiz.models.Question (found in field 'questions.title')

错误是在 setUpFirestore() 中发现的,并且是由于以下行:Log.d("DATA", value.toObjects(Quiz::class.java).toString()) {根据 logcat 错误}

我的主要活动:

    package com.example.quiz.activities

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.MenuItem
import android.widget.Toast
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.recyclerview.widget.GridLayoutManager
import com.example.quiz.R
import com.example.quiz.adapters.QuizAdapter
import com.example.quiz.databinding.ActivityMainBinding
import com.example.quiz.models.Quiz
import com.google.android.material.datepicker.MaterialDatePicker
import com.google.firebase.firestore.DocumentSnapshot
import com.google.firebase.firestore.FirebaseFirestore
import java.text.SimpleDateFormat
import java.util.*

class MainActivity() : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    lateinit var actionBarDrawerToggle: ActionBarDrawerToggle
    lateinit var adapter: QuizAdapter
    private var quizList = mutableListOf<Quiz>()
    lateinit var firestore : FirebaseFirestore

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        setUpViews()
    }

    fun setUpViews(){
        setUpFirestore()
        setUpDrawerLayout()
        setUpRecyclerView()
        setUpDatePicker()
    }

    private fun setUpDatePicker() {
        val btnDatePicker = binding.btnDatePicker
        btnDatePicker.setOnClickListener{
            val datePicker = MaterialDatePicker.Builder.datePicker().build()
            datePicker.show(supportFragmentManager,"DatePicker")
            datePicker.addOnPositiveButtonClickListener {
                Log.d("DATEPICKER",datePicker.headerText)
                val dateFormatter =  SimpleDateFormat("dd-mm-yyyy")
                val date = dateFormatter.format(Date(it))
                val intent = Intent(this,QuestionActivity::class.java)
                intent.putExtra("DATE",date)
                startActivity(intent)
            }
            datePicker.addOnNegativeButtonClickListener {
                Log.d("DATEPICKER",datePicker.headerText)
            }
            datePicker.addOnCancelListener {
                Log.d("DATEPICKER","Date Picker was cancelled")
            }
        }
    }

    private fun setUpFirestore() {
        firestore = FirebaseFirestore.getInstance()
        val collectionReference = firestore.collection("quizzes")
        collectionReference.addSnapshotListener{ value,error ->
            if(value == null || error != null){
                Toast.makeText(this,"Error fetching data",Toast.LENGTH_SHORT).show()
                return@addSnapshotListener
            }
            Log.d("DATA", value.toObjects(Quiz::class.java).toString())
            quizList.clear()
            quizList.addAll(value.toObjects(Quiz::class.java))
            adapter.notifyDataSetChanged()
        }
    }

    private fun setUpRecyclerView(){
        val quizRecyclerView = binding.quizRecyclerView
        adapter = QuizAdapter(this,quizList)
        quizRecyclerView.layoutManager = GridLayoutManager(this,2)
        quizRecyclerView.adapter = adapter
    }

    fun setUpDrawerLayout(){
        val appBar = binding.appBar
        val mainDrawer = binding.mainDrawer
        val navigationView = binding.navigationView
        setSupportActionBar(appBar)
        actionBarDrawerToggle = ActionBarDrawerToggle(this,mainDrawer,
            R.string.app_name,
            R.string.app_name
        )
        actionBarDrawerToggle.syncState()
        navigationView.setNavigationItemSelectedListener {
            val intent = Intent(this,ProfileActivity::class.java)
            startActivity(intent)
            mainDrawer.closeDrawers()
            true
        }
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        if (actionBarDrawerToggle.onOptionsItemSelected(item)){
            return true
        }
        return super.onOptionsItemSelected(item)
    }
}


我的问题模型如下:

package com.example.quiz.models

data class Question(
    var description: String = "",
    var option1: String = "",
    var option2: String = "",
    var option3: String = "",
    var option4: String = "",
    var answer: String = "",
    var userAnswer:String=""
)

我的测验模型是-

package com.example.quiz.models

import com.google.firebase.auth.FirebaseAuth

data class Quiz(
    var id: String = "",
    var title: String = "",
    var questions: MutableMap<String, Question> = mutableMapOf()
)

数据库图片:

database image

logcat 错误是-

2022-04-24 17:19:04.678 12341-12341/com.example.quiz E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.quiz, PID: 12341
    java.lang.RuntimeException: Could not deserialize object. Can't convert object of type java.lang.String to type com.example.quiz.models.Question (found in field 'questions.title')
        at com.google.firebase.firestore.util.CustomClassMapper.deserializeError(CustomClassMapper.java:568)
        at com.google.firebase.firestore.util.CustomClassMapper.convertBean(CustomClassMapper.java:549)
        at com.google.firebase.firestore.util.CustomClassMapper.deserializeToClass(CustomClassMapper.java:258)
        at com.google.firebase.firestore.util.CustomClassMapper.deserializeToType(CustomClassMapper.java:194)
        at com.google.firebase.firestore.util.CustomClassMapper.deserializeToParameterizedType(CustomClassMapper.java:296)
        at com.google.firebase.firestore.util.CustomClassMapper.deserializeToType(CustomClassMapper.java:192)
        at com.google.firebase.firestore.util.CustomClassMapper.access0(CustomClassMapper.java:57)
        at com.google.firebase.firestore.util.CustomClassMapper$BeanMapper.deserialize(CustomClassMapper.java:775)
        at com.google.firebase.firestore.util.CustomClassMapper$BeanMapper.deserialize(CustomClassMapper.java:746)
        at com.google.firebase.firestore.util.CustomClassMapper.convertBean(CustomClassMapper.java:547)
        at com.google.firebase.firestore.util.CustomClassMapper.deserializeToClass(CustomClassMapper.java:258)
        at com.google.firebase.firestore.util.CustomClassMapper.convertToCustomClass(CustomClassMapper.java:103)
        at com.google.firebase.firestore.DocumentSnapshot.toObject(DocumentSnapshot.java:183)
        at com.google.firebase.firestore.QueryDocumentSnapshot.toObject(QueryDocumentSnapshot.java:116)
        at com.google.firebase.firestore.QuerySnapshot.toObjects(QuerySnapshot.java:184)
        at com.google.firebase.firestore.QuerySnapshot.toObjects(QuerySnapshot.java:166)
        at com.example.quiz.activities.MainActivity.setUpFirestore$lambda-4(MainActivity.kt:95)
        at com.example.quiz.activities.MainActivity.$r8$lambda$ALF8Ugv5XcVyBlrGHEr70w5PaxM(Unknown Source:0)
        at com.example.quiz.activities.MainActivity$$ExternalSyntheticLambda5.onEvent(Unknown Source:4)
        at com.google.firebase.firestore.Query.lambda$addSnapshotListenerInternal$com-google-firebase-firestore-Query(Query.java:1205)
        at com.google.firebase.firestore.Query$$ExternalSyntheticLambda2.onEvent(Unknown Source:6)
        at com.google.firebase.firestore.core.AsyncEventListener.lambda$onEvent[=17=]$com-google-firebase-firestore-core-AsyncEventListener(AsyncEventListener.java:42)
        at com.google.firebase.firestore.core.AsyncEventListener$$ExternalSyntheticLambda0.run(Unknown Source:6)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

您遇到以下错误:

Could not deserialize object.Can't convert object of type java.lang.String to type com.example.quiz.models.Question (found in field 'questions.title')

因为使用这行代码时:

Log.d("DATA", value.toObjects(Quiz::class.java).toString())

这意味着您正在尝试将每个文档转换为 Quiz 类型的 object,这实际上是不可能的。为什么?因为每个文档应该包含一个 questions 数组,该数组应该由 only Question object 组成。但这并没有发生,因为该数组还包含一个名为 title 的字符串。正如我在您的测验 class 中看到的那样,标题字段应该是直接在文档中的字段,并且应该 而不是 出现在数组中。要解决此问题,您必须从数组中删除标题并将其添加为文档中的字段。