Reputation:
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
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
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
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