I am trying to make a simple GET API call from Android app via Retrofit and Kotlin.
What I am struggling with is getting the data from a certain tag of response.
I am using Django rest framework with pagination, therefore results are enclosed in tag results
. I can't figure out how to look into this results
tag i.o. the whole response from retrofit.
My response:
{
"count": 13,
"next": null,
"previous": null,
"results": [
{
"id": 2,
"passport_number": 11233546,
"first_name": "Egor",
"last_name": "Wexler",
"email": "string",
"age": 0,
"city": "city"
},
...
{ <other customers> },
]
}
Customer.kt
import com.google.gson.annotations.SerializedName
data class Customer(
@SerializedName("passport_number") val passportNumber: Int,
@SerializedName("first_name") val firstName: String,
@SerializedName("last_name") val lastName: String,
@SerializedName("email") val email: String,
@SerializedName("age") val age: Int,
@SerializedName("city") val city: String
)
ApiInterface.kt
interface ApiInterface {
@GET("customers/")
fun getCustomers() : Call<List<Customer>>
companion object {
fun create() : ApiInterface {
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.build()
return retrofit.create(ApiInterface::class.java)
}
}
}
MainActivity.kt
val apiInterface = ApiInterface.create()
apiInterface.getCustomers().enqueue(
object : Callback<List<Customer>> {
override fun onResponse(call: Call<List<Customer>>, response: Response<List<Customer>>) {
// logic for success
}
override fun onFailure(call: Call<List<Customer>>, t: Throwable) {
t.message // java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
}
}
)
So the code eventually went to onFailure
with the message that I put in the comment.
If I disable pagination on server - it works as expected because the response turns to what is according to app expectations (list of objects Customer
).
But I want the app to look into tag results since it actually contains the response.
I feel like this should be trivial to do but can't find how.
I saw a lot of answers for the similar question marked by "Expected BEGIN_ARRAY but was BEGIN_OBJECT" but none of them solves my issue.
You should create a response class that follows the same structure as your response.
In your case something like this will do:
data class PageResult(
val count: Int,
val next: Int?,
val previous: Int?,
val results: List<Customer>
)
And in your API interface use:
@GET("customers/")
fun getCustomers() : Call<PageResult>