All the API JSON responses would have the following structure:
{
"status": <Integer>
"data": <Object or List of Objects>
"message": <String>
}
the only property that changes is the 'data', which can be any object or list of object. So is there a way to create a BaseResponse class like
open class BaseResponse<T> (
@SerializedName("status")
val status: Int,
@SerializedName("data")
abstract val `data`: T,
@SerializedName("message")
val message: String
)
and the response classes
data class HelloResponse (
override val `data`: Hello
) : BaseResponse<Hello> {
data class Hello (
@SerializedName("hello")
val hello: String
)
}
data class HellosResponse (
override val `data`: List<Hello>
) : BaseResponse<List<Hello>> {
data class Hello (
@SerializedName("hello")
val hello: String
)
}
What i really want is to only override the data property, so that i don't have to write status and message property for each Response sub data class i write. I dont want to write status and message in my sub class and pass it to base class, cause i'd still write both the properties, so no difference than creating a data class with status and message.
so cannot be like
data class HelloResponse (
val status: Int,
override val `data`: Hello,
val message: String
) : BasicResponse<Hello>(status, `data`, message) {
data class Hello (
@SerializedMessage("hello")
val hello: String
)
}
Edit: Own Answer
Well I realized that the HelloResponse is actually a waste since i'm only using it to access the actual Hello class. So what i did was to use the Base class directly in Retrofit2 service. Eg:
fun hello(): Call<BaseResponse<Hello>>
or
fun hellos(): Call<BaseResponse<List<Hello>>>
Well you have to directly specify the type with BaseResponse everywhere you use it. Maybe create typeallias
Or you can create alias
typealias HelloResponse = BaseResponse<Hello>
typealias HellosResponse = BaseResponse<List<Hello>>
To manually deserialize json string with Gson, you need to use TypeToken parameter instead of class type.
val hello = Gson().fromJson<BaseResponse<Hello>>(jsonStr, object: TypeToken<BaseResponse<Hello>>(){}.type)
If you use
val hello = Gson().fromJson<BaseResponse<Hello>>(jsonStr, BaseResponse::class.java)
The data property doesn't convert to Hello instead converts to LinkedHashMap
Note: Retrofit2's GsonConverterFactory uses TypeToken internally, so no problem.