anon
anon

Reputation:

How to make base class accept generics which have different key

I am getting a response something like this where status, message & data keys will remain the same across the different API responses & only the content inside the data JSON object will change, in this example, I have a JSON object with a member key in other response I can have tournament key.

{
    "status": true,
    "message": "Success",
    "data": {
          "member": {
          "id": 21,
          "emailAddress": "[email protected]",
          "firstName": "ABC"
        }
    }
}

Currently, I am making use of generics and doing something like this

data class SignInResponse(
    val `data`: Data<Member>
) : BaseResponse()

and BaseResponse class has common JSON keys that I am getting, Here I'm using generics in Data class passing the JSON class that is changing.

open class BaseResponse {
    val status: Boolean  = false
    val message: String  = UNDEFINED
}
@Keep
data class Data<T>(val actualData: T)

But this approach is incomplete because the above code will expect a JSON key actualData but here JSON key can be a member , tournament , or anything. How can I pass the class in Data class so that it can support the above JSON response?

Upvotes: 0

Views: 921

Answers (3)

anon
anon

Reputation:

I ended up using the following approach, where I create a generic for data class

data class BaseResponse<T>(
    val status: Boolean, val message: String, val data: T
)

Above implementation enables me to pass model of changing JSON Object inside the data field

data class SignInResponse(
    val token: String, val member: Member
)

and after summing up everything we can use it like this

interface BasicxBookingServices {
    @POST(Urls.SIGNIN_URL)
    suspend fun signIn(@Body body: SignInRequest): Response<BaseResponse<SignInResponse>>
}

Upvotes: 0

Joffrey
Joffrey

Reputation: 37720

One way to represent this would be via a class hierarchy rather than generics, because this extra wrapping is not present in the JSON, nor in your conceptual data structure. A sealed class is what I would usually go for in this case.

However, it all depends on which JSON serialization library you're using. If you control both ends of the communication, I would definitely go for Kotlinx Serialization, which supports sealed hierarchies (and polymorphism in general) in a nice way.

If you don't control the serialization side, maybe a temporary union of all fields as @Chris mentioned is your simplest option.

Upvotes: 1

Chris
Chris

Reputation: 5191

Is this as a result from a network call? I've never used generics in trying to parse incoming network calls before.

I'd have a baseData class that contains any common fields between member or tournament - like id or name and then subclass that with a concrete implementation for each possibility which would hold the unique data.

then your BaseResponse class could just be

data class BaseResponse(
    val status: Boolean
    val message: String
    val data: BaseData
)

Upvotes: 1

Related Questions