How can I create a model for this API (Kotlin-Retrofit)?

Viewed 29

I'm using https://www.api-football.com to get football countries and leagues, Json response for countries is like this:

{
"get": "countries",
"parameters": [],
"errors": [],
"results": 164,
"paging": {
    "current": 1,
    "total": 1
},
"response": [
    {
        "name": "Albania",
        "code": "AL",
        "flag": "https://media.api-sports.io/flags/al.svg"
    },
    {
        "name": "Algeria",
        "code": "DZ",
        "flag": "https://media.api-sports.io/flags/dz.svg"
    },
    {
        "name": "Andorra",
        "code": "AD",
        "flag": "https://media.api-sports.io/flags/ad.svg"
    },
    

    ...

I tried to create a model like this:

Here is the CountryData data class:

data class CountryData (
val code: String,
val flag: String,
val name: String
)

And here is the Country data class which uses CountryData and use them in a list:

data class Country(
val results : List<CountryData>
)

But those models give me some errors: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was NUMBER at line 1 column 61 path $.results

And I think that's because of the api response type is not a list of CountryData.

So if that's the problem, I want to get only the part after "response": [ ... But I don't know how to do this.

If you think another problem causes this error please let me know.

By the way, here is the api interface:

interface FootballApi {

@Headers("X-RapidAPI-Key: $API_KEY")
@GET(GET_COUNTRIES)
suspend fun getCountries() : Response<Country>
}

And here is my Retrofit Instance :

object RetrofitInstance {

val api: FootballApi by lazy {
    Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build()
        .create(FootballApi::class.java)
}
}
2 Answers

I solved this problem by adding other data models to my project. Here is the Country data class:

data class Country(
val code: String,
val flag: String,
val name: String
)

Here is the CountryResponse data class:

data class CountryResponse (
val get: String,
val parameters: List<Any>,
val errors: List<Any>,
val results: Int,
val paging: Paging,
val response: List<Country>
)

Here is the Paging data class:

data class Paging(
val current: Int,
val total: Int
)

And now I can get the country list by response.body()!!.response

The problem you had in the first place is that parameter names in your model do matter! At first you tried to unmarshal the JSON data into the wrong model:

data class Country(
val results : List<CountryData>
)

The JSON field with all the countries in it has the name response like this:

"response": [
    {
        "name": "Albania",
        "code": "AL",
        "flag": "https://media.api-sports.io/flags/al.svg"
    },
    ...

So if you use the same attribute in your model it should work without the need of adding all the other attributes (which you probably don't need) to your model:

data class Country(
val response: List<CountryData>
)
Related