Retrofit Gson转换异常 begin array but was object 解决方案

最近跟朋友在一起吃饭,发现现在很多人都已经在用retrofit 来做为网络请求框架!谈到其中一个问题就是跟后台的沟通问题,我以前的项目后台返回给我的数据都是按照这样返回给我的: 如果正常返回result 对应的是一个jsonArray, 如果返回的错误信息,result 对应的就是一个空的数组,而不是返回给我的json对象!,这样来说,retrofit 解析是完全没有问题的,也就是说你的bean 的结构是什么样,就必须要后台按照那个结构给你 -----------

后来新项目,后台新架构,对,问题出现了,对的 ,就是大家看到的这个错误

begin array but was object

而且后台直接拒绝以前后台的做法,原因是他们有一个拦截器,错误信息直接给你拦截掉了,哈哈,尴尬了,拦截器是统一的,改的成本太大,so ,自己想办法吧 ,也是百度,google了一番,最后也是找到了这样一种解决方案:再retrofit拿到response 之后,拦截判断一下.如果是正常的response code 就直接放行,如果不是,就直接抛出一个自定义的异常类,这个异常类包含errorCode,和errorMsg ,对的,这些已经够我们用了!下面上代码,为了让其他人少走弯路就直接把代码贴上了,直接拿走,不要客气!

首先上正常用retrofit创建

4262301-cc06555ef7134628.png

这个我就上图片了,因为你们也用不到,我们就是从GsonConverterFactory入手,需要自定义一个转换器

CustomGsonConverterFactory

public final class CustomGsonConverterFactory extends Converter.Factory {
    public static CustomGsonConverterFactory create() {
        return create(new Gson());
    }
    public static CustomGsonConverterFactory create(Gson gson) {
        return new CustomGsonConverterFactory(gson);
    }

    private final Gson gson;

    private CustomGsonConverterFactory(Gson gson) {
        if (gson == null) throw new NullPointerException("gson == null");
        this.gson = gson;
    }

    @Override
    public Converter responseBodyConverter(Type type, Annotation[] annotations,
                                                            Retrofit retrofit) {
        TypeAdapter adapter = gson.getAdapter(TypeToken.get(type));
//返回一个自定义的ResponseConverter   重点都在这里面
        return new CustomResponseConverter<>(gson, adapter,type);
    }

    @Override
    public Converter requestBodyConverter(Type type, Annotation[]         parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        TypeAdapter adapter = this.gson.getAdapter(TypeToken.get(type));
//返回一个自定义的RequestBodyConverte   这个就直接把retrofit 的GsonConverterFactory 里面的RequestBodyConverte   复制过来到自己的定义的类就行了
        return new GsonRequestBodyConverter(this.gson, adapter);
    }
}

从上面注释大家也就知道了,重点是CustomResponseConverter ,因为所有的处理逻辑都在里面,下面贴这个类的代码,有兴趣的可以看下源码,对比下自定义和源码的区别

CustomResponseConverterimplements

final class CustomResponseConverter implements Converter {
    private final Gson gson;
    private TypeAdapter adapter;
    private Type mType;

    CustomResponseConverter(Gson gson, TypeAdapter mAdapter, Type mType) {
        this.gson = gson;
        this.adapter = mAdapter;
        this.mType = mType;
    }

    @Override
    public T convert(ResponseBody value) throws IOException {

        ErrorResponse errorResponse = new ErrorResponse();
        try {
            String body = value.string();
            JSONObject json = new JSONObject(body);
            String code = json.getString("respCode");
            String msg = json.getString("respMsg");
            if (Constant.RESPCODE.equals(code)) {
//此处的RESPCODE为你和后台约定返回的正常的responseCode
                return gson.fromJson(body, mType);
            } else {
                errorResponse = gson.fromJson(body, ErrorResponse.class);
                //ErrorResponse  为自定义的错误类
                //抛一个自定义ResultException 传入失败时候的状态码,和信息
                throw new ResultException(errorResponse.getRespCode(), errorResponse.getRespMsg());
            }
        } catch (Exception e) {
            throw new ResultException(errorResponse.getRespCode(), errorResponse.getRespMsg());
        } finally {
            value.close();
        }

    }
}

自定义的CustomGsonConverterFactory所需要的元素都已经到位了,下面就是替换掉原生的GsonConverterFactory


4262301-ac7e26b28bc298d2.png

OK小伙伴们,就是这么简单,为了小伙伴更轻松的解决问题,我把所需要的类,都贴在下面,是不是懂你呢
ErrorResponse

public class ErrorResponse {


    public ErrorResponse(){
        this.respCode= "";
        this.respMsg="";
    }


    /**
     *
     */
    private String respCode;

    /**
     *
     */
    private String respMsg;

    public String getRespCode() {
        return respCode;
    }

    public void setRespCode(String respCode) {
        this.respCode = respCode;
    }

    public String getRespMsg() {
        return respMsg;
    }

    public void setRespMsg(String respMsg) {
        this.respMsg = respMsg;
    }

    @Override
    public String toString() {
        return "ErrorResponse{" +
                "respCode='" + respCode + '\'' +
                ", respMsg='" + respMsg + '\'' +
                '}';
    }
}

自定义的 ResultExceptionextends

public class ResultExceptionextends RuntimeException {

private StringrespMsg;

    private StringrespCode;

    public ResultException(String respCode, String respMsg) {

this.respMsg = respMsg;

        this.respCode = respCode;

    }

public StringgetRespMsg() {

return respMsg;

    }

public void setRespMsg(String respMsg) {

this.respMsg = respMsg;

    }

public StringgetRespCode() {

return respCode;

    }

public void setRespCode(String respCode) {

this.respCode = respCode;

    }

}

OK 到此结束!

你可能感兴趣的:(Retrofit Gson转换异常 begin array but was object 解决方案)