DdM
DdM

Reputation: 3

RxJava+Retrofit+Gson JsonSyntaxException on server error response

I have REST POST call create order as Observable<OrderResponse>, when order create call is successful everything is fine, but then server returns error I get com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $ because Gson does not know how to handle json that have different fields than my response model

Server error response:

[{
    "code": 99,
    "message": "Please check your request"
}]

OrderResponse

data class OrderResponse(

    @Expose
    var orderId: String,

    @Expose
    var redirectUrl: String,

    @Expose
    var validUntil: Long

)

RxJava subscription

repository.requestCreateNewOrder(newOrder)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(object : Observer<OrderResponse> {
                        override fun onComplete() {                  
                        }

                        override fun onSubscribe(d: Disposable) {
                            compositeDisposable.add(d)
                        }

                        override fun onNext(t: OrderResponse) {
                        }

                        override fun onError(t: Throwable) {
                          //HERE I GET JsonSyntaxException
                        }
                    })

Retrofit Service

interface OrderService {
@Headers(
        "Content-Type: application/x-www-form-urlencoded ",
        "Connection: Keep-Alive",
        "Accept-Encoding: application/json",
        "User-Agent: Fiddler"
)
@FormUrlEncoded
@POST("/createOrder")
fun createOrder(@Field("orderId") orderId: String,
                @Field("payCurrency") payCurrency: String,
                @Field("payAmount") payAmount: Double,
                @Header("Content-Length") length: Int): Observable<OrderResponse>}

Anyone have any suggestions for how to pass retrofit or gson the error model to know how to handle it

Upvotes: 0

Views: 902

Answers (2)

kuljeet singh
kuljeet singh

Reputation: 2852

As per your code you are only handling the success response

but you need to handle your error response too for this you need to ensure that your API should send you error codes different then 200 (success response generally greater then 200 and less then 300 i.e code >= 200 && code < 300 ) because retrofit consider 200-299 as success

You can achieve this simply by changing your observable return type to

 Observable<Response< OrderResponse>>

and after receiving response from server simply check

           if (orderResponse.isSuccessful()) {
              //here you can handle success by using orderResponse.getbody()
            } else {
                 // here you can display error message and if you further want 
                // to parse error response from server then use below function
                errorOrderResponseHandling(orderResponse);
            }

you want to further parse response into error model(in this example OrderAPIError is model class for error response) then below is the function

 private void errorOrderResponseHandling(Response<OrderResponse> orderResponse) {
        OrderAPIError orderAPIError = null;
        try {
            orderAPIError = new Gson().fromJson(String.valueOf(new 
            JSONObject(orderResponse.errorBody().string())), OrderAPIError.class);
           // further orderAPIError object you can fetch server message and display 
            it to user as per your requirement
        } catch (JSONException e) {
            e.printStackTrace();

        } catch (IOException e) {
            e.printStackTrace();

        }
    }

Above example is in android not in kotlin but you can get idea and use function accordingly in kotlin

Upvotes: 0

Avinash Verma
Avinash Verma

Reputation: 2762

As you are using GSON to parse the JSON.

Your JSON sucessfull response will be something like

{
    "orderId": 1,
    "redirectUrl": "url",
    "validUntil": 12414194
}

while for error response your JSON response start with Array.

[{
    "code": 99,
    "message": "Please check your request"
}]

So tell to server guy to not add the error response in Array [].

If you are getting the response as Array then you have to use list.

repository.requestCreateNewOrder(newOrder)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(object : Observer<List<OrderResponse>> {
                        override fun onComplete() {                  
                        }

                        override fun onSubscribe(d: Disposable) {
                            compositeDisposable.add(d)
                        }

                        override fun onNext(t: OrderResponse) {
                        }

                        override fun onError(t: Throwable) {
                          //HERE I GET JsonSyntaxException
                        }
                    })

In Observer response you have to add as List if your JSON response start with Array like error.

Solution : Correct it from backend for not adding Error Response in ARRAY.

Upvotes: 0

Related Questions