预期为 BEGIN_ARRAY,但在第 1 行第 2 列路径 $ 处为 BEGIN_OBJECT。改造2安卓

问题描述 投票:0回答:1

你能帮我写一下代码吗?我不明白还需要做什么。我已经尝试了一切,但现在我不明白还能做什么。

我需要获取“entries”数组来检索数据。这是正在解析的 JSON 的链接: https://launchercontent.mojang.com/news.json

package com.mcbedrock.app.data

data class NewsEntry(

    val version: Int,

    val entries: List<Entry>

)

data class Entry(

    val cardBorder: Boolean,

    val category: String,

    val date: String,

    val id: String,

    val newsPageImage: NewsPageImage,

    val newsType: List<String>,

    val playPageImage: PlayPageImage,

    val readMoreLink: String,

    val tag: String,

    val text: String,

    val title: String

)

data class NewsPageImage(

    val dimensions: Dimensions,

    val title: String,

    val url: String

)

data class PlayPageImage(

    val title: String,

    val url: String

)

data class Dimensions(

    val height: Int,

    val width: Int

)



My adapter:

package com.mcbedrock.app.adapter

import android.content.Context

import android.view.LayoutInflater

import android.view.View

import android.view.ViewGroup

import android.widget.ImageView

import androidx.recyclerview.widget.RecyclerView

import com.bumptech.glide.Glide

import com.google.android.material.button.MaterialButton

import com.google.android.material.textview.MaterialTextView

import com.mcbedrock.app.R

import com.mcbedrock.app.data.NewsEntry

class NewsAdapter(var context: Context, var newsEntryList: MutableList<NewsEntry>):

    RecyclerView.Adapter<NewsAdapter.MyViewHolder>() {

    inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        var titleView: MaterialTextView

        var textView: MaterialTextView

        var imageView: ImageView

        var readMoreBtn: MaterialButton

        init {

            titleView = itemView.findViewById(R.id.TitleView)

            textView = itemView.findViewById(R.id.TextView)

            imageView = itemView.findViewById(R.id.ImageView)

            readMoreBtn = itemView.findViewById(R.id.ActionButton)

        }

    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NewsAdapter.MyViewHolder {

        return MyViewHolder(LayoutInflater.from(context).inflate(R.layout.item_news_card, parent, false))

    }

    override fun onBindViewHolder(holder: NewsAdapter.MyViewHolder, position: Int) {

        val entry = newsEntryList[position].entries[position]

        holder.titleView.text = entry.title

        holder.textView.text = entry.text

        Glide.with(context)

            .load("https://launchercontent.mojang.com/" + entry.newsPageImage.url)

            .into(holder.imageView)

    }

    override fun getItemCount(): Int {

        return newsEntryList.size

    }

}


My fragment:

package com.mcbedrock.app.ui.fragment

import android.os.Bundle

import android.util.Log

import androidx.fragment.app.Fragment

import android.view.LayoutInflater

import android.view.View

import android.view.ViewGroup

import androidx.lifecycle.ViewModelProvider

import androidx.navigation.fragment.findNavController

import androidx.recyclerview.widget.LinearLayoutManager

import androidx.recyclerview.widget.RecyclerView

import androidx.recyclerview.widget.RecyclerView.LayoutManager

import com.mcbedrock.app.R

import com.mcbedrock.app.adapter.NewsAdapter

import com.mcbedrock.app.databinding.FragmentFirstBinding

import com.mcbedrock.app.viewmodel.NewsViewModel

class FirstFragment : Fragment() {

    var viewModel: NewsViewModel? = null

    var recyclerView: RecyclerView? = null

    var adapter: NewsAdapter? = null

    var layoutManager: LayoutManager? = null

    private var _binding: FragmentFirstBinding? = null

    private val binding get() = _binding!!

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)

    }

    override fun onCreateView(

        inflater: LayoutInflater, container: ViewGroup?,

        savedInstanceState: Bundle?): View? {

        _binding = FragmentFirstBinding.inflate(inflater, container, false)

        return binding.root

    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

        super.onViewCreated(view, savedInstanceState)

        recyclerView = _binding?.recyclerview

        layoutManager = LinearLayoutManager(requireActivity())

        recyclerView!!.layoutManager = layoutManager

        viewModel = ViewModelProvider(this)[NewsViewModel::class.java]

        viewModel!!.getNewsList.observe(viewLifecycleOwner) { newsEntry ->

            if (newsEntry != null) {

                Log.e("NewsFragment", "NewsList: " + newsEntry.get(0).entries.get(0).title)

                if (newsEntry != null) {

                    adapter = NewsAdapter(requireActivity(), newsEntry)

                    adapter!!.notifyDataSetChanged()

                    recyclerView!!. adapter = adapter

                }

            }

        }

        binding.buttonFirst.setOnClickListener {

            findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)

        }

    }

    override fun onDestroyView() {

        super.onDestroyView()

        _binding = null

    }

}

我尝试修改数据类并结合适配器中的数据检索。

android json kotlin mvvm retrofit2
1个回答
0
投票

看起来您已指定

List<NewsEntry>
作为请求的返回类型,因此序列化库尝试将其解析为
JsonArray
,但由于响应是
JsonObject
,因此失败。

  1. 要使其正常工作,您可以尝试将

    List<NewsEntry>
    替换为
    NewsEntry
    并进行所有其他相关更改。

  2. 或者,您可以考虑使用类型适配器来删除

    NewsEntry
    模型,以便您的返回类型为
    List<Entry>
    。如果你使用 Gson,它可能看起来像这样:

class EntriesTypeAdapterFactory : TypeAdapterFactory {

    private val typeToken: TypeToken<List<Entry>> = object : TypeToken<List<Entry>>() {}

    override fun <R : Any?> create(gson: Gson, type: TypeToken<R>): TypeAdapter<R>? {
        if (!typeToken.isAssignableFrom(type.type)) {
            return null
        }
        val delegateAdapter = gson.getDelegateAdapter(this, typeToken)
        val elementAdapter = gson.getAdapter(JsonElement::class.java)
        val result = object : TypeAdapter<List<Entry>>() {
            override fun write(out: JsonWriter, value: List<Entry>) {
                //we don't serialize it so no logic specified
            }

            override fun read(`in`: JsonReader): List<Entry>? {
                val jsonElement = elementAdapter.read(`in`)
                return delegateAdapter.fromJsonTree(
                    (jsonElement as JsonObject).getAsJsonArray("entries")
                )
            }
        }.nullSafe()

        return result as TypeAdapter<R>
    }
}

之后添加到Gson中,如下:

.registerTypeAdapterFactory(EntriesTypeAdapterFactory())
© www.soinside.com 2019 - 2024. All rights reserved.