0

I am using Retrofit 2.4.0, with GsonConverterFactory and RxJavaFactory.

Suppose I am now calling an API named getSomething.

In normal situations, server returns

{
    status: "ok",
    errorMsg: "",
    data: {...}
}

But if an error occurs:

{
    status: "error",
    errorMsg: "Some error message",
    data: []
}

Note that data becomes an array if an error occurs.

This is how I define the API:

@GET("URL")
fun getSomething(): Observable<SomeResponse<SomeObject>>

SomeResponse:

open class SomeResponse<T> {

    var data: T? = null

    @SerializedName("errorMsg")
    var errorMessage: String? = ""

    var status: String? = ""
}

And in an APIManager (Singleton):

fun getSomething(): Observable<SomeObject> {
    return someAPI.getSomething()
            .map{ response ->
                if (response.status != "ok") throw new APIException(response.errorMessage)
                response.data
            }
            .subscribeOn(Schedulers.io())
            .unsubscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
}

As you can see, if status is not "ok", an APIException which I defined by myself will be thrown with the error message returned from server, so that I can have my own handling (e.g. display a dialog with that error message).

But now it cannot even reach that throw.
Since data is now an array, an JsonSyntaxException is thrown instead, and therefore I cannot show the correct error message to user.

What I want to do

I know that I can delay the parsing of data after I check the status, by making all declarations of Retrofit interface to return Observable<SomeResponse<Any>>, and do:

            .map{ response ->
                if (response.status != "ok") throw new APIException(response.errorMessage)
                response.data
            }
            .map{ data ->
                //Parse the object here
            }

Assume I don't want to do that, still relying on GsonConverterFactory to do the parsing, is there a way to throw APIException with correct error message?

Community
  • 1
  • 1
Sira Lam
  • 5,179
  • 3
  • 34
  • 68
  • 1
    if we use Gson then json object or json array both aree considered as JsonElement , so you can recieve data as JsonElement and then use it as json object or json array coz in oop Parent can hold refrence of child – Adeel Turk Jun 12 '18 at 09:48
  • 1
    You can refer this [https://stackoverflow.com/questions/24279245/how-to-handle-dynamic-json-in-retrofit](https://stackoverflow.com/questions/24279245/how-to-handle-dynamic-json-in-retrofit) – Krishna Jun 12 '18 at 10:18

2 Answers2

0

For this case, you will have to manual parse the response, As Adeel suggested, take 'data' as JsonElement.

When you get {status: "error"} i.e. exception case, you can show the error message, Otherwise in case of {status: "ok"}, you can get JsonArray from 'data' and use that array.

Surabhi Singh
  • 803
  • 8
  • 14
0

Just as an alternative,

If you are using Kotlin, you can bypass this issue declaring the variable as "Any".

@SerializedName("my_parameter")
@Expose
var myVar: Any ?= null
ZLNK
  • 811
  • 14
  • 17