Ошибка при отображении данных из модернизации: ожидаемый BEGIN_ARRAY, но был BEGIN_OBJECT в строке 1, столбце 2, пути $ - PullRequest
0 голосов
/ 15 января 2020

Я пытаюсь получить данные для моего приложения с помощью модернизации, данные регистрируются, но они не отображаются. Я продолжаю получать эту ошибку

Ожидаемый BEGIN_ARRAY, но был BEGIN_OBJECT в строке 1, путь 2 столбца $

Не уверен, что делаю неправильно.

Ответ выглядит примерно так

   {
        info: {
        count: 493,
        pages: 25
        },
        results: [
          {
            id: 1,
            name: "Rick Sanchez",
            status: "Alive",
            species: "Human",
            gender: "Male",
            image: "https://rickandmortyapi.com/api/character/avatar/1.jpeg",
          },
             // more characters
        ]
    }

Мой класс данных выглядит следующим образом

    data class Character(
    @SerializedName("results")
    val results: List<Results>,

    @SerializedName("info")
    val info: List<Info>

)
data class Results(
    @SerializedName("id")
    val id: Int,

    @SerializedName("name")
    val name: String,

    //
)

Вот так выглядит мой адаптер

    class CharacterAdapter(var characters: ArrayList<Character>): RecyclerView.Adapter<CharacterAdapter.CharacterViewHolder>() {

    fun updateCharacters(newCharacters: List<Character>) {
        characters.clear()
        characters.addAll(newCharacters)
        notifyDataSetChanged()
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = CharacterViewHolder(
        LayoutInflater.from(parent.context).inflate(R.layout.character_item, parent, false)
    )

    override fun getItemCount() = characters.size

    override fun onBindViewHolder(holder: CharacterViewHolder, position: Int) {
        holder.bind(characters[position])
    }

    class CharacterViewHolder(view: View): RecyclerView.ViewHolder(view){
        private val characterName = view.characterName
        private val progressDrawable = getProgressDrawable(view.context)

        fun bind(character:Character){
            characterName.text = character.results[adapterPosition].name
        }
    }
}

Моя ViewModel

    class CharacterViewModel: ViewModel() {

    @Inject
    lateinit var charactersService: CharactersService

    init {
        DaggerApiComponent.create().inject(this)
    }

    private val disposable = CompositeDisposable()

    val characters = MutableLiveData<List<Character>>()
    val charactersLoadError = MutableLiveData<Boolean>()
    val loading = MutableLiveData<Boolean>()

    fun refresh(){
        fetchCharacters()
    }


    private fun fetchCharacters(){
        loading.value = true
        disposable.add(
            charactersService.getCharacters()
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeWith(object : DisposableSingleObserver<List<Character>>(){
                    override fun onSuccess(value: List<Character>?) {
                        characters.value = value
                        charactersLoadError.value = false
                        loading.value = false
                    }

                    override fun onError(e: Throwable?) {
                        //
                        Log.e(TAG, "${e?.message}")
                    }

                })
        )
    }

    override fun onCleared() {
       //
    }
}

Моя активность

class MainActivity : AppCompatActivity() {

    lateinit var viewModel: CharacterViewModel
    private val characterAdapter = CharacterAdapter(arrayListOf())

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        viewModel = ViewModelProviders.of(this).get(CharacterViewModel::class.java)
        viewModel.refresh()

        charactersList.apply {
            layoutManager = LinearLayoutManager(context)
            adapter = characterAdapter
        }

        swipeRefresh.setOnRefreshListener {
            swipeRefresh.isRefreshing = false
            viewModel.refresh()
        }

        observeViewModel()
    }

    private fun observeViewModel(){
        viewModel.characters.observe(this, Observer { characters ->
            characters?.let{
                charactersList.visibility = View.VISIBLE
                characterAdapter.updateCharacters(it)
            }
        })

        viewModel.charactersLoadError.observe(this, Observer { isError ->

        })

        viewModel.loading.observe(this, Observer { isLoading ->
            isLoading?.let{ loadingView.visibility = if(it) View.VISIBLE else View.GONE
                if(it) {

                    charactersList.visibility = View.GONE
                }
            }

        })
    }
}

Ответы [ 2 ]

1 голос
/ 15 января 2020

Вы указываете информацию в виде списка, но объект ожидается. Вы можете исправить свой cra sh, изменив тип свойства:

@SerializedName("info")
val info: Info

И я полагаю, вы возвращаете List из своего сервиса, но в Json есть объект:

 CharactersService.getCharacters(): Character
0 голосов
/ 16 января 2020

Итак, у меня возникла проблема: я неправильно писал класс Model

data class CharacterModel(
    val results: List<CharResult>
)

data class CharResult(
    val created: String,
    val episode: List<String>,
    val gender: String,
    val id: Int,
    val image: String,
    val location: Location,
    val name: String,
    val origin: Origin,
    val species: String,
    val status: String,
    val type: String,
    val url: String
)

data class Location(
    val name: String,
    val url: String
)

data class Origin(
    val name: String,
    val url: String
)

PS Я нашел очень удобный android студийный плагин, который поможет вам создать модель под названием

JSON К Kotlin Печать класса (JsonToKotlinClass)

...