Android Gson 解析Json数据过程和如何自定义解析规则(下)

上两篇文章主要讲述寻找问题根源到解决思路,解决办法比较复杂,这里提供一种最简单的解决办法,不需要改动太多的东西:

比如一般后台返回的数据格式如下:

正常数据

{"code":200,"data":{"id":"adsd","name":"Weipru"},"msg":"success","timeStamp":"20191015102953"}

不存在data的数据

{"code":1000,"data":"","msg":"请登录!","timeStamp":"20191014094718"}

对应我们自己的Http响应实体


public class HttpMessage<T> {
    private int code;
    private T data;
    private String msg;
    private String timeStamp;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public String getTimeStamp() {
        return timeStamp;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public void setTimeStamp(String timeStamp) {
        this.timeStamp = timeStamp;
    }
    
}

正常访问后台流程

  • 后台API
public interface GsonTestAPI {
    @GET("/user/list")
    Call<HttpMessage<List<UserAuthen>>> getUserList();

    @GET("/user/info")
    Call<HttpMessage<UserInfo>> getUserInfo();
}
  • 调用API,获取数据
  messageCall.enqueue(new Callback<HttpMessage<UserInfo>>() {
            @Override
            public void onResponse(Call<HttpMessage<UserInfo>> call, Response<HttpMessage<UserInfo>> response) {
                Log.i(TAG, "onResponse: " + response.body().getCode());
            }

            @Override
            public void onFailure(Call<HttpMessage<UserInfo>> call, Throwable t) {
                Log.i(TAG, "onResponse: " + t.getMessage());
                t.printStackTrace();
            }
        });

同理,data类型为泛型数组时:

  Call<HttpMessage<List<UserAuthen>>> messageCall = userServiceAPI.getUserList();
        messageCall.enqueue(new Callback<HttpMessage<List<UserAuthen>>>() {
            @Override
            public void onResponse(Call<HttpMessage<List<UserAuthen>>> call, Response<HttpMessage<List<UserAuthen>>> response) {
                Log.i(TAG, "onResponse: " + response.body().getCode());
            }

            @Override
            public void onFailure(Call<HttpMessage<List<UserAuthen>>> call, Throwable t) {
                Log.i(TAG, "onResponse: " + t.getMessage());
                t.printStackTrace();
            }
        });

如果返回正常数据,则可以正确解析并返回,否正直接抛出异常,怎么解决呢?

同样也需要自定义一个自己的转换器,需要三个类:

  • GsonConverFactory
  • GsonResponseBodyConverter
     
  • GsonRequestBodyConverter

直接从源码中复制出来 换成自己的名字即可,,现在只处理响应体转换器GsonResponseBodyConverter,代码如下:

  • 在GsonConverFactory中返回自己的转换器,至展示关键部分

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                            Retrofit retrofit) {
        Log.w("TYPE", "类型是 " + type.getTypeName());//
        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        return new WGsonResponseBodyConverter<>(gson, adapter);
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type,
                                                          Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        return new WGsonRequestBodyConverter<>(gson, adapter);
    }
  • 在WGsonResponseBodyConverter中做状态判断:
 public T convert(ResponseBody value) throws IOException {
        try {
            //因为value只能被读取一次,所以这里必须把读取结果存起来,给下次使用
            String reponseString = value.string();
            HttpMessage httpMessage = gson.fromJson(reponseString, HttpMessage.class);
            if (httpMessage.getCode() != 200) {
                return (T) httpMessage;//直接返回,data字段不做类型转换
            }

            MediaType contentType = value.contentType();
            Charset charset = contentType != null ? contentType.charset(UTF_8) : UTF_8;
            InputStream inputStream = new ByteArrayInputStream(reponseString.getBytes());
            Reader reader = new InputStreamReader(inputStream, charset);
            JsonReader jsonReader = gson.newJsonReader(reader);

            return adapter.read(jsonReader);
        } finally {
            value.close();
        }
    }

使用自定义的转换器即可:

 userServiceAPI = new Retrofit.Builder()
                .client(builder.build())
                .baseUrl(this.host).addConverterFactory(WGsonConverFactory.create())//使用自己的转换器
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build()
                .create(GsonTestAPI.class);

简单而完美地解决问题

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值