I was trying to get info from this api in my kotlin app https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=BTC,USD,EUR but when i run it i get the onFailure: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

this is my code:

the class MyData:

package com.example.myapplication
data class MyData(

val BTC: Double,

val EUR: Double,

val USD: Double
)

this is my ApiInterface:

package com.example.myapplication
import retrofit2.Call
import retrofit2.http.GET
interface ApiInterface {
@GET("data/price?fsym=ETH&tsyms=BTC,USD,EUR")

fun getData(): Call<List<MyData>>

}

And this is is my MainActivity.kt

package com.example.myapplication

import android.os.Bundle

import android.util.Log
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.lang.StringBuilder

const val Base_Url = "https://min-api.cryptocompare.com/"

class MainActivity : AppCompatActivity() {

private lateinit var txtId: TextView

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

    txtId = findViewById(R.id.txtId)


}

private fun getMyData() {
    val retrofitBuilder = Retrofit.Builder()
        .addConverterFactory(GsonConverterFactory.create())
        .baseUrl(Base_Url)
        .build()
        .create(ApiInterface::class.java)

    val retrofitData = retrofitBuilder.getData()

    retrofitData.enqueue(object : Callback<List<MyData>?> {
        override fun onResponse(call: Call<List<MyData>?>, response: Response<List<MyData>?>) {

            val responseBody = response.body()!!

            val myStringBuilder = StringBuilder()
            for (MyData in responseBody) {
                myStringBuilder.append(MyData.BTC)
            }

            txtId.text = myStringBuilder

        }



        override fun onFailure(call: Call<List<MyData>?>, t: Throwable) {
            Log.d("MainActivity", "onFailure: "+t.message)


        }
    })
}

}

and i get: com.example.myapplication D/MainActivity: onFailure: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

I really hope someone could help me with it!


Solution 1:

Please change the function signature in the ApiInterface to:

interface ApiInterface {
    @GET("data/price?fsym=ETH&tsyms=BTC,USD,EUR")
    fun getData(): Call<MyData>
}

JSON you expect is looking like this:

{"BTC":0.07761,"USD":3334.47,"EUR":2923.18}

It is neither an array or list, it is an object, so you need to return an object from that function Call<MyData>, not a list of objects Call<List<MyData>>.

In MainActivity:

retrofitData.enqueue(object : Callback<MyData?> {
    override fun onResponse(call: Call<MyData?>, response: Response<MyData?>) {

        val responseBody = response.body()
        val myStringBuilder = StringBuilder()
        if (responseBody != null) {
            myStringBuilder.append(responseBody.BTC)
        }

        txtId.text = myStringBuilder

    }



    override fun onFailure(call: Call<MyData?>, t: Throwable) {
        Log.d("MainActivity", "onFailure: "+t.message)

    }
})