Somesh
04/26/2021, 4:39 PMstatus
, 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": "<mailto:abc@xyz.com|abc@xyz.com>",
"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?Roukanken
04/26/2021, 4:49 PMBaseResponse<T>
which will also have val data: T
member
and then you would be parsing DataResponse<SignInData>
type, where SignInData
would be whatever you want:
data class SignInData(
val member: Member
)
Roukanken
04/26/2021, 4:51 PMT
is before looking at json, which seem only dependent on what API you are callingRoukanken
04/26/2021, 5:14 PM// Your framework
inline fun <reified T> parse(text: String): T = TODO()
// Model
data class BaseResponse<T> (
val status: Boolean,
val message: String,
val data: T,
)
data class SignInData(
val member: Member
)
data class TournamentData(
val tournament: Tournament
)
// Parse
val signInResponse = parse<BaseResponse<SignInData>>("")
val tournamentResponse = parse<BaseResponse<TournamentData>>("")
// these will exists in the model
val tournament: Tournament = tournamentResponse.data.tournament
val member: Member = signInResponse.data.member
Somesh
04/27/2021, 5:17 AMRoukanken
04/27/2021, 6:33 AM/api/signIn
will give you will get you member
in data, /api/tournament
will get you tournament
in data and so on) then imho this is the correct way.
I would question the API design though, and if you are controlling the other end, I would think of designing the API differently - eg smth like
data class SignIn(
val info: BasicResponseInfo,
val member: Member,
)
data class BasicResponseInfo(
val status: Boolean,
val message: String,
)
would be more friendly, or by using sealed classes to have Response.Error
class and Response.Success
but these would need changes from the API side - if we are just fitting it to that API, then the one I showed ya is the best way imho.
Also if the responses can differ in structure based on parameters (eg, /api?getWhat=signIn
, /api?getWhat=tournament
, or similar) then I would look into sealed classes, but unsure if you can fit that without API changes - usually you need a "discriminator" so your JSON would need to have type
field or similar:
"data": {
"type": "Tournament",
"tournament": ...
}
(PS: writing in Slack with code is so ugh, I hope it looks correct on your end, cause Slack is smacking me every 2 lines)Somesh
04/27/2021, 7:48 AMIf you are just using api like this...Yes, This is how my API works.
I would question the API design though...I have passed this to our API developer
writing in Slack with code is so ughYes, same thing happed with me when I was writing the question Thank you for all the help. 🙏🏽