2

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?

allo86
  • 946
  • 1
  • 9
  • 23

0 Answers0