How can I customise the actual response in model class itself using Retrofit Android?

Viewed 28

I'm explaining thorugh one example, so please try to understand the below scenario:

Let's say from API I'm getting this response:

{
  "data": {
    "hot": [
      {
        "name": "OnePlus 6 (Mirror Black 6GB RAM + 64GB memory)",
        "price": "34999",
        "image_url": "https://images-eu.ssl-images-amazon.com/images/I/41DZ309iN9L._AC_US160_.jpg",
        "key": 2
      }
    ],
    "cold": [
      {
        "name": "OnePlus 6 (Mirror Black 6GB RAM + 64GB memory)",
        "price": "34999",
        "image_url": "https://images-eu.ssl-images-amazon.com/images/I/41DZ309iN9L._AC_US160_.jpg",
        "value": 4
      }
    ],
    "widget": {
      "test": "Hello"
    }
  }
}

Now, normally using Retrofit + GSON, we use model classes like this:

Temperature

    data class Temperature(
    val `data`: Data
)

Data

    data class Data(
    val cold: List<Cold>,
    val hot: List<Hot>,
    val widget: Widget
)

Cold

data class Cold(
    val image_url: String,
    val name: String,
    val price: String,
    val value: Int
)

Hot

data class Hot(
    val image_url: String,
    val key: Int,
    val name: String,
    val price: String
)

Widget

data class Widget(
    val test: String
)

Requirement

What I want is, my model class should design differently. If I created a custom class like this:

Widget

data class Widget(
    val map: LinkedHashMap<Int, Int>
)

Inside this map, using Retrofit, I want that:

map key should store as: Hot class "key" field

map value should store as: Cold class "value" field

Please note, I do not want to extract data and then manually create map object, iterate loop and store it in any view or other layer class. I need something automated. May be using any converter factory?

1 Answers

I don't know a way to get both the data class and HashMap representation of a response from Retrofit at the same time, but one solution you can try is to get the data classes from Retrofit and convert them to Maps by yourself whenever you need that.

To convert a data class to a Map<String, Any> you can use any serialization library. Using Gson, you can use these helper functions:

val gson = GsonBuilder()
    .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE)
    .create()

//convert a data class to a map
fun <T> T.serializeToMap(): Map<String, Any> {
    return convert()
}

//convert a map to a data class
inline fun <reified T> Map<String, Any>.toDataClass(): T {
    return convert()
}

//convert an object of type I to type O
inline fun <I, reified O> I.convert(): O {
    val json = gson.toJson(this)
    return gson.fromJson(json, object : TypeToken<O>() {}.type)
}

Usage:

val temperature = // Your Temperature data class that you received from Retrofit
val map = temperature.serializeToMap()
Related