AkylbekSultanov77
AkylbekSultanov77

Reputation: 37

Android json mapping retrofit

I have problem with mapping json getting by request using Retrofit. I have dynamic 'data' object with similar nested object's.

{
  "data": {
    "DZ": {
      "country": "Algeria",
      "region": "Africa"
    },
    "AO": {
      "country": "Angola",
      "region": "Africa"
    },
    "BJ": {
      "country": "Benin",
      "region": "Africa"
    },
    "BW": {
      "country": "Botswana",
      "region": "Africa"
    },
    "BF": {
      "country": "Burkina Faso",
      "region": "Africa"
    },
    "BI": {
      "country": "Burundi",
      "region": "Africa"
    },
    "CV": {
      "country": "Cabo Verde",
      "region": "Africa"
    },
    "CM": {
      "country": "Cameroon",
      "region": "Africa"
    },
    "CF": {
      "country": "Central African Republic (the)",
      "region": "Africa"
    },
    "TD": {
      "country": "Chad",
      "region": "Africa"
    }
  }
}

Any suggestion how deal with it? I want to collect all object's in one list.

Upvotes: 1

Views: 1739

Answers (2)

AkylbekSultanov77
AkylbekSultanov77

Reputation: 37

everyone. I solved this problem using mapping. Also I used Moshi in order to convert json to kotlin model class, Retrofit for API call and Coroutines for easy asynchronous code

Below header data class which hold map of a country

@JsonClass(generateAdapter = true)
data class MainModel(

    val data : Map<String, Country>

    )

Country class

@JsonClass(generateAdapter = true)
data class Country(
    @Json(name = "country")
    val country : String,
    @Json(name = "region")
    val region : String

)

My api interface

interface Api {

    @GET("data/v1/countries?limit=251") suspend fun getAllCountries(): Response<MainModel>


    companion object {
        var api: Api? = null
        fun getInstance() : Api {
            if (api == null) {
                val retrofit = Retrofit.Builder()
                    .baseUrl("https://api.first.org/")
                    .addConverterFactory(MoshiConverterFactory.create())
                    .addCallAdapterFactory(CoroutineCallAdapterFactory())
                    .build()
                api = retrofit.create(Api::class.java)
            }
            return api!!
        }

    }
}

function in viewmodel class where I call api request

fun getAllCountries() {
       
        viewModelScope.launch {
            try {
                
                val response = repository.getAllCountries()
                
                withContext(Dispatchers.Main) {
                    if (response.isSuccessful) {
                        //do your code
                        
                    } else {
                        
                        onError("Error : ${response.message()} ")
                    }
                }
            } catch (e: IOException) {
                onError(e.message!!)
            }


        }

    }

Here is useful links that help me understand Coroutines https://medium.com/android-beginners/mvvm-with-kotlin-coroutines-and-retrofit-example-d3f5f3b09050

https://blog.mindorks.com/using-retrofit-with-kotlin-coroutines-in-android

Upvotes: 1

Akshat Tiwari
Akshat Tiwari

Reputation: 389

You can resolve this issue by making data classes in Kotlin as follows:

data class MajorData(
    val `data`: Data
)

data class Data(
    val AO: AO,
    val BF: BF,
    val BI: BI,
    val BJ: BJ,
    val BW: BW,
    val CF: CF,
    val CM: CM,
    val CV: CV,
    val DZ: DZ,
    val TD: TD
)

Now you will basically pass the response from the retrofit call to the MajorData class.

Now for better clarity, you should also make data classes for all objects such as AO,DZ, etc.

Example: (Taking AO into consideration)

data class AO(
    val country: String,
    val region: String
)

Please make the same for others as well.

Hope this helps you out. Happy Coding! :)

Upvotes: 1

Related Questions