服务器错误响应上的RxJava + Retrofit + Gson JsonSyntaxException

时间:2018-08-09 07:51:06

标签: android kotlin retrofit2 rx-java2 gson

我有REST POST调用创建订单为Observable<OrderResponse>,成功完成订单创建调用后,一切都很好,但是服务器返回错误,我得到了com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $,因为Gson不知道如何处理具有字段与我的响应模型不同

服务器错误响应:

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

OrderResponse

data class OrderResponse(

    @Expose
    var orderId: String,

    @Expose
    var redirectUrl: String,

    @Expose
    var validUntil: Long

RxJava订阅

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
                        }
                    })

改装服务

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>}

任何人对如何通过改造或gson错误模型以了解如何处理它都有任何建议

2 个答案:

答案 0 :(得分:0)

使用GSON解析JSON时。

您的JSON成功响应将类似于

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

对于错误响应,您的JSON响应以数组开头。

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

所以告诉服务器人员不要在数组[]中添加错误响应。

如果您将响应作为Array获得,则必须使用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
                        }
                    })

如果您的JSON响应以Array之类的错误开头,则必须在Observer响应中添加为List。

解决方案:从后端进行更正,以免在ARRAY中不添加错误响应。

答案 1 :(得分:0)

根据您的代码,您仅处理成功响应

,但是您也需要处理错误响应,因此您需要确保您的API发送给您的错误代码应不同于200(成功响应通常大于200且小于300,即代码> = 200 &&代码<300)因为改造将200-299视为成功

您只需将可观察的返回类型更改为

即可实现此目的
 Observable<Response< OrderResponse>>

并且在收到服务器的响应后,只需进行检查

           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);
            }

您想进一步将响应解析为错误模型(在本示例中,OrderAPIError是错误响应的模型类),然后是函数

 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();

        }
    }

上面的示例不是在kotlin中的android系统中,但您可以在kotlin中了解并相应地使用功能