Kotlin.Android。预期 BEGIN_ARRAY 但在第 1 行第 2 列路径 $ 处 BEGIN_OBJECT

Kotlin.Android. Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

我 运行 今天在启动 app.I 时遇到了同样的问题 非常感谢您帮助解决了我的问题。 Api 和 JSON - https://swapi.dev/api/people/

错误代码如下:

错误

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.skreep.starwarsappandroid, PID: 20521
    java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
        at com.google.gson.stream.JsonReader.beginArray(JsonReader.java:350)
        at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:80)
        at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
        at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:40)
        at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:27)
        at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:243)
        at retrofit2.OkHttpCall.onResponse(OkHttpCall.java:153)
        at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)

这是代码型号

data class Characters(
    @SerializedName("name")
    val characters: String,
    @SerializedName("gender")
    val gender: String
)

这是代码模型(字符列表)

class CharacterList: ArrayList<Characters>()

这是我的 ViewModel 的代码

class HomeViewModel() : ViewModel() {

    var repository = StarWarsRepository()
    val list: MutableLiveData<Response<CharacterList>> = MutableLiveData()

    fun getCharacterViewModel() {
        viewModelScope.launch {
            list.value = repository.getCharacters()
        }
    }
}

这是我的界面代码

@GET("people/")
    suspend fun getCharacters(): Response<CharacterList>

这是代码我的片段

class HomeFragment : Fragment() {

    private var _binding: FragmentHomeBinding? = null
    private val binding get() = _binding!!
    private lateinit var viewModel: HomeViewModel
    lateinit var recyclerView: RecyclerView
    private lateinit var adapter: HomeListAdapter

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        viewModel = ViewModelProvider(this)[(HomeViewModel::class.java)]
        _binding = FragmentHomeBinding.inflate(inflater, container, false)
        val view = binding.root

        recyclerView = binding.recycler
        adapter = HomeListAdapter()
        recyclerView.layoutManager= LinearLayoutManager(requireContext())
        recyclerView.adapter = adapter
        getCharacterViewModel()
        return view

    }

    private fun getCharacterViewModel(){

        viewModel.getCharacterViewModel()
        viewModel.list.observe(this, { list ->
            list.body()?.let { adapter.setList(it) }
        })
    }

}

适配器

package com.skreep.starwarsappandroid.ui.fragments.home.adapter

import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.skreep.starwarsappandroid.data.remote.model.Characters
import com.skreep.starwarsappandroid.databinding.ItemCharacterBinding


class HomeListAdapter() :
    RecyclerView.Adapter<HomeListAdapter.HomeViewHolder>() {
    var peopleList = emptyList<Characters>()

    class HomeViewHolder(var binding: ItemCharacterBinding) :
        RecyclerView.ViewHolder(binding.root) {

    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeViewHolder {
        return HomeViewHolder(
            ItemCharacterBinding.inflate(
                LayoutInflater
                    .from(parent.context), parent, false
            )
        )
    }

    override fun onBindViewHolder(holder: HomeViewHolder, position: Int) {
        val characterList = peopleList[position]
        holder.binding.characterName.text = characterList.characters
        holder.binding.characterGender.text = characterList.gender
    }

    override fun getItemCount(): Int {
        return peopleList.size
    }

    @SuppressLint("NotifyDataSetChanged")
    fun setList(list: List<Characters>) {
        peopleList = list
        notifyDataSetChanged()
    }


    }

您需要创建额外的模型来将 json 解析为,例如调用它 CharactersResponse 并在请求函数中使用它而不是 CharacterList。所以它将如下所示:

data class CharactersResponse(
    @SerializedName("results")
    val charactersList: CharacterList
)

@GET("people/")
suspend fun getCharacters(): Response<CharactersResponse>

您错过了来自 json 表示的 results 对象,其中存储了字符:

{
  "count": 82, 
  "next": "https://swapi.dev/api/people/?page=2", 
  "previous": null, 
  "results": [ ...