提问人:IbremMiner837 提问时间:10/15/2023 更新时间:10/15/2023 访问量:32
预期为 BEGIN_ARRAY,但在第 1 行第 2 列路径 $ 处BEGIN_OBJECT。Retrofit2 Android [复制]
Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $. Retrofit2 Android [duplicate]
问:
你能帮我写代码吗?我不明白还需要做什么。我已经尝试了一切,现在我不明白那里还能做些什么。
我需要获取“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
}
}
我尝试修改数据类并在适配器中组合数据检索。
答:
0赞
Vlad Guriev
10/15/2023
#1
看起来您已指定为请求的返回类型,因此序列化库尝试将其解析为 ,但由于响应是 .List<NewsEntry>
JsonArray
JsonObject
要使其正常工作,您可以尝试替换并进行所有其他相关更改。
List<NewsEntry>
NewsEntry
或者,可以考虑使用类型适配器来删除模型,以便返回类型为 .如果您使用的是 Gson,它可能如下所示:
NewsEntry
List<Entry>
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())
评论