Home > database >  how to write Kotlin Base class for multiple data class for multiple similar API JSON response struct
how to write Kotlin Base class for multiple data class for multiple similar API JSON response struct

Time:03-19

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
    )
}

CodePudding user response:

If you don't want to write status and message properties for data subclasses then you cannot expect subclass to have a constructor with status and message magically.

I strongly suggest you to make BaseResponse abstract and make subclasses like following

abstract class BaseResponse<T> {
    @SerializedName("status")
    abstract val status: Int

    @SerializedName("message")
    abstract val message: String

    @SerializedName("data")
    abstract val `data`: T
}

data class HelloResponse (
    override val status: Int,
    override val message: String,
    override val `data`: Hello,
) : BaseResponse<Hello>() {
    data class Hello (
        @SerializedMessage("hello")
        val hello: String
    )
}

You can achieve it in a way you don't need to write override val properties for subclass declarations by sacrificing data classes. However you lose all bounties provided by data class.

abstract class BaseResponse<T> {
    @SerializedName("status")
    abstract val status: Int

    @SerializedName("message")
    abstract val message: String

    @SerializedName("data")
    abstract val `data`: T
}

class HelloResponse: BaseResponse<Hello>() {
    data class Hello (
        @SerializedMessage("hello")
        val hello: String
    )
}

Just a kind reminder, you don't need to use @SerializedName annotation if class property name and json property name are same.

  • Related