如何使用 Retrofit 解析对象内部的对象数组 json

How to parse json array of objects inside object using Retrofit

我正在尝试解析 JSON (https://raw.githubusercontent.com/Biuni/PokemonGO-Pokedex/master/pokedex.json) 以在 RecyclerView 中显示数据,但出现错误:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.myapplication, PID: 13534
    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:39)
        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)

我看到问题是 JSON 只包含 1 个对象(口袋妖怪),并且在这个对象中有不同的口袋妖怪数组。我不知道如何解析 JSON 中上层对象中的数组。我应该改变什么才能让它发挥作用? 我想我应该保存这个 pokemon 对象然后解析它,但我不知道如何进入它。 谢谢。

API接口:

interface SimpleApi {
    @GET("pokedex.json")
    suspend fun getCustomPosts(): Response<List<Post>>
}

存储库:

class Repository {
    suspend fun getCustomPosts(): Response<List<Post>>{
        return RetrofitInstance.api.getCustomPosts()
    }
}

视图模型:

class MainViewModel(val repository: Repository) : ViewModel() {

    val myCustomPosts = MutableLiveData<Response<List<Post>>>()

    fun getCustomPosts() {
        viewModelScope.launch {
            val response: Response<List<Post>> = repository.getCustomPosts()
            myCustomPosts.value = response
        }
    }
}

主要活动:

class MainActivity : AppCompatActivity() {

    private lateinit var viewModel: MainViewModel
    private lateinit var binding: ActivityMainBinding
    private lateinit var recyclerView: RecyclerView
    private lateinit var adapter: MyAdapter


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)
        setRecyclerView()

        val repository = Repository()
        val viewModelFactory = MainViewModelFactory(repository)
        viewModel = ViewModelProvider(this, viewModelFactory).get(MainViewModel::class.java)

        viewModel.getCustomPosts()

        viewModel.myCustomPosts.observe(this, Observer { response ->
            if (response.isSuccessful) {
                response.body()?.let { adapter.setData(it) }
            } else {
                Toast.makeText(this, response.code(), Toast.LENGTH_SHORT).show()
            }
        })
    }

    private fun setRecyclerView() {
        adapter = MyAdapter()
        recyclerView = binding.recyclerView
        recyclerView.layoutManager = LinearLayoutManager(this)
        recyclerView.adapter = adapter
    }
}

RecyclerView 适配器:

class MyAdapter() : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {

    private var postList = emptyList<Post>()

    class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val idView: TextView = view.findViewById(R.id.id_txt)
        val nameView: TextView = view.findViewById(R.id.name_txt)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        return MyViewHolder(
            LayoutInflater.from(parent.context).inflate(R.layout.row_layout, parent, false)
        )
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val currentItem = postList[position]
        holder.idView.text = currentItem.id.toString()
        holder.nameView.text = currentItem.name
    }

    override fun getItemCount(): Int = postList.size


    fun setData(newList: List<Post>){
        postList = newList
        notifyDataSetChanged()
    }
}

Post:

data class Post(
    @SerializedName("id")
    val id: Int,
    @SerializedName("name")
    val name: String
)

尝试在响应对象中使用下一个 class:

data class PokedexResponse (
    @SerializedName("pokemon")
    val pokemons: List<Post>
)

interface SimpleApi {
    @GET("pokedex.json")
    suspend fun getCustomPosts(): Response<PokedexResponse>
}

我猜你错过了解析 pokemon 对象:

{
  "pokemon": [{ ... }]
}