I have to work with a server that sends these responses for any request:
For OK: HTTP 200
{
"jsonrpc": "2.0",
"id": null,
"result": {
"data": {
"exp": 1635637589,
...
...
},
"success": true,
"errors": [],
"messages": []
}
}
For error: HTTP 200 (yes, and unfortunately that can't be changed)
{
"jsonrpc": "2.0",
"id": null,
"result": {
"data": {},
"success": false,
"errors": [{
"code": 1001,
"message": "Error"
}],
"messages": []
}
}
Notice that data
is a json object of a specific type when the response is OK, and a different one when the response is an error. This format is used for all the responses, meaning that data
can have different child fields.
I want to use Retrofit
+ Moshi
+ RxJava
, but I am struggling to find a way to deserialize the response to handle that data
field using two different types. I have this model:
data class BaseResponse<T>(
@Json(name = "jsonrpc") val jsonrpc: String,
@Json(name = "id") val id: String?,
@Json(name = "result") val result: BaseResponseResult<T>
)
data class BaseResponseResult<T>(
@Json(name = "data") val data: T, // This is what I have a problem with
@Json(name = "success") val success: Boolean,
@Json(name = "errors") val errors: List<Error>
)
// This would be the data field
data class LoginResponse(
@Json(name = "user_id") val userId: Long,
...
...
...
)
// This would be the data field
data class ProfileResponse(
@Json(name = "name") val name: String,
...
...
...
)
And this would be my Retrofit interface
interface UsersApi {
@POST("api/login")
fun loginReal(@Body request: BaseRequest<LoginRequest>): Single<BaseResponse<LoginResponse>>
@POST("api/profile")
fun loginReal(@Body request: BaseRequest<ProfileRequest>): Single<BaseResponse<ProfileResponse>>
}
I thought about adding a custom deserializer to parse BaseResponse<T>
and throw some exception in case the response was an error one, but I am not able to register a deserializer using generics. I have read Moshi's documentation and several posts about deserializers, but I can't get it to work with a generic. Is that possible with Moshi?