【问题标题】:retrofit error : Expected BEGIN_OBJECT but was BEGIN_ARRAY改造错误:预期为 BEGIN_OBJECT 但为 BEGIN_ARRAY
【发布时间】:2017-05-16 08:59:56
【问题描述】:

我做了一个功能:输入身份证号码,点击提交按钮,然后获取身份证的基本信息。

我使用的模型:

public class IdCardInfo {

    private int errNum;
    private String retMsg;
    private RetDataBean retData;

    public int getErrNum() {
        return errNum;
    }

    public void setErrNum(int errNum) {
        this.errNum = errNum;
    }

    public String getRetMsg() {
        return retMsg;
    }

    public void setRetMsg(String retMsg) {
        this.retMsg = retMsg;
    }

    public RetDataBean getRetData() {
        return retData;
    }

    public void setRetData(RetDataBean retData) {
        this.retData = retData;
    }

    public static class RetDataBean {

        private String sex;
        private String birthday;
        private String address;

        public String getSex() {
            return sex;
        }

        public void setSex(String sex) {
            this.sex = sex;
        }

        public String getBirthday() {
            return birthday;
        }

        public void setBirthday(String birthday) {
            this.birthday = birthday;
        }

        public String getAddress() {
            return address;
        }

        public void setAddress(String address) {
            this.address = address;
        }
    }
}

我使用的改造界面:

@GET("apistore/idservice/id")
Observable<IdCardInfo> getIdCardInfo(@Query("id") String id);

当我输入正确的身份证号码时,一切正常。返回的结果是:

{
    "errNum": 0,
    "retMsg": "success",
    "retData": {
        "sex": "M", 
        "birthday": "1987-04-20", 
        "address": "some place" 
    }
}

一切正常。

但是当我输入错误的身份证号码时,就会发生不好的事情:

Caused by: java.lang.IllegalStateException: 
Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 86 path $.retData

返回结果为:

{
    "errNum": -1, 
    "retMsg": "Incorrect ID card number!", 
    "retData": [ ]
}

我该如何修复这些错误?

【问题讨论】:

  • 显示您的请求代码

标签: android gson retrofit rx-java


【解决方案1】:

api@apistore/idservice/id 返回一个空的 json 数组而不是一个空的 json 对象。你在这里期待一个 json 对象,所以它会抛出。您可以控制 API 返回的内容吗?请返回

{
    "errNum": -1, 
    "retMsg": "Incorrect ID card number!", 
    "retData": { }
}

在响应中。

【讨论】:

  • @singdhu 很抱歉这么说:我无法控制 API 返回的内容。
【解决方案2】:

返回数组时应该使用响应列表 例如:

@GET("apistore/idservice/id")
 Observable<List<IdCardInfo>> getIdCardInfo(@Query("id") String id);

代替

@GET("apistore/idservice/id")
 Observable<IdCardInfo> getIdCardInfo(@Query("id") String id);

在你的改造电话中也替换

Call<List<IdCardInfo>> call = service.getIdCardInfo("query");
        call.enqueue(new Callback<List<IdCardInfo>>() {

            @Override
            public void onResponse(Call<List<IdCardInfo>> variant, Response<List<IdCardInfo>> response) {
                if (response != null && response.isSuccessful() && response.errorBody() == null) {


                }
            }

            @Override
            public void onFailure(Call<List<IdCardInfo>> variant, Throwable t) {
                t.printStackTrace();

            }
        });

【讨论】:

    【解决方案3】:

    这是服务器在没有数据的情况下返回空数组的问题,您的服务器 API 很可能基于某些 PHP 框架。

    它只能从后端而不是从 app 排序,因为你不能在不改变类结构的情况下解析 Array 而不是 object。

    所以请询问您的后端团队是否可以更改该内容,即。空数组到空对象或不应该发送任何键。

    在这种情况下可能会被破解:

    是的,我知道确切的问题,因为它处于框架级别,所以不能轻易更改。我建议你可以改变你的代码 这个

    @GET("apistore/idservice/id")
    Observable<JsonObject> getIdCardInfo(@Query("id") String id);
    

    因此,在此之后您需要手动解析代码,然后您需要将特定的键解析放在 try-catch 块中。 ie. 在 try 块中,如果遇到异常,您将尝试将数据解析为对象,然后将 null 分配给该对象值。

    【讨论】:

    • 感谢您的建议,可惜服务端API是通用API,无法更改返回。于是问题就出来了。
    • 非常感谢。我从你的回答中得到了很多。
    猜你喜欢
    • 2020-07-26
    • 2015-07-24
    • 2014-08-01
    • 2015-11-26
    • 2018-03-27
    • 2016-06-28
    • 2019-02-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多