android retrofit 实战自定义converter,解决相同接口返回不同数据的问题
2017-01-10 23:51
633 查看
square的retrofit是目前比较火的网络框架,我目前也在用
今天项目上遇到一个问题,就是请求同一个接口,可能返回不同的json格式
例如,访问一个登录接口,成功的时候,返回的是
{
"code": 0,
"message": "登录成功",
"data": {
"username": "xxx",
"userId": "xxx"
}
}
我们首先定义一个basebean
然后定义一个loginbean去接收数据
访问失败的时候,服务器自动转发了地址,返回服务器维护的提示
{
"code": 1,
"message": "服务器维护中",
"data": {
"title": "xxx",
"content": "xxx"
}
}
而我们通常用retrofit写接口,都是通过下面这种方式
而我们通常在初始化时候,都会添加如下代码
这里的
返回的是一个converterFactory,就是用于我们的json解析的
如果我们用的converter是默认的GsonConverter的话,retrofit就会按照
loginbean的格式解析,当访问异常的时候,json返回的格式变了,json自然就解析失败了。
于是我想过很多方法,例如把泛型换成base,到回调的时候再继续解析
但是想想,以后所有的接口都要这么写,岂不是要吐血?
那么,我们如何通过不修改泛型,又可以实现数据的正常解析呢?
我采用的解决办法是自定义converter
首先在base中扩展一个字段
不多说,Notify的代码就不贴了,看converter
上面代码可以看到,我们先去解析code,然后判断不同的code去做不同的解析,
当返回的数据是停服公告时,就将解析到的data,封装到notify里面去,就可以避免json解析的异常
也可以正常返回数据
接下来自定义一个converterFactory
其实就是把源码复制下来改了改。最后,把converter改成自己的converter
不过这么写也有局限性,就是当使用这个converter时,所有的bean都要继承base类,
而且每当服务器改变一种结构,我们都必须修改converter
这样会相当麻烦,暂时没有想到更好的解决办法,如果有大神有更好的办法欢迎指教
本人qq184497436
今天项目上遇到一个问题,就是请求同一个接口,可能返回不同的json格式
例如,访问一个登录接口,成功的时候,返回的是
{
"code": 0,
"message": "登录成功",
"data": {
"username": "xxx",
"userId": "xxx"
}
}
我们首先定义一个basebean
public class Base { public String message; public int code; }
然后定义一个loginbean去接收数据
public class LoginBean extends Base{ public LoginContent data; public class LoginContent { public String username; public String userId; } }
访问失败的时候,服务器自动转发了地址,返回服务器维护的提示
{
"code": 1,
"message": "服务器维护中",
"data": {
"title": "xxx",
"content": "xxx"
}
}
而我们通常用retrofit写接口,都是通过下面这种方式
@FormUrlEncoded @POST("user/login") Observable<LoginBean> login(@Field("userInfo.mobile") String mobile, @Field("userInfo.passWord") String pwd);这里把泛型写死成了loginbean,
而我们通常在初始化时候,都会添加如下代码
new Retrofit.Builder() .baseUrl(Constants.SERVER_URL) .addConverterFactory(GsonConverterFactory.create()) //添加回调库,采用RxJava .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .client(genericClient()) .build();
这里的
GsonConverterFactory.create()
返回的是一个converterFactory,就是用于我们的json解析的
如果我们用的converter是默认的GsonConverter的话,retrofit就会按照
loginbean的格式解析,当访问异常的时候,json返回的格式变了,json自然就解析失败了。
于是我想过很多方法,例如把泛型换成base,到回调的时候再继续解析
但是想想,以后所有的接口都要这么写,岂不是要吐血?
那么,我们如何通过不修改泛型,又可以实现数据的正常解析呢?
我采用的解决办法是自定义converter
首先在base中扩展一个字段
public class Base { public String message; public int code; public Notify notify; }
不多说,Notify的代码就不贴了,看converter
public class MyGsonResponseBodyConverter<T extends Base> implements Converter<ResponseBody, T> { private final Gson gson; private final Type type; public MyGsonResponseBodyConverter(Gson gson, Type type) { this.gson = gson; this.type = type; } @Override public T convert(ResponseBody value) throws IOException { String json = value.string(); JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject(); // 解析code JsonPrimitive jsonPrimitive = jsonObject.getAsJsonPrimitive("code"); int code = 0; if (jsonPrimitive != null) { code = jsonPrimitive.getAsInt(); } // 解析message JsonElement jsonElement = jsonObject.get("message"); String message = null; if (jsonElement != null) { massage = jsonElement.getAsString(); } T t = null; try { // 通过反射获取泛型的实例对象 Class<T> clazz = (Class<T>) type; t = clazz.newInstance(); } catch (Exception e) { e.printStackTrace(); } if (code == 1 ) { // 按停服公告的格式解析,封装到notify字段中 t.notify = gson.fromJson(jsonObject.getAsJsonObject("data"), Notify.class); } else { // 按标准格式解析 return gson.fromJson(json, type); } return t; } }
上面代码可以看到,我们先去解析code,然后判断不同的code去做不同的解析,
当返回的数据是停服公告时,就将解析到的data,封装到notify里面去,就可以避免json解析的异常
也可以正常返回数据
接下来自定义一个converterFactory
public class MyGsonConverterFactory extends Converter.Factory { /** * Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and * decoding from JSON (when no charset is specified by a header) will use UTF-8. */ public static MyGsonConverterFactory create() { return create(new Gson()); } /** * Create an instance using {@code gson} for conversion. Encoding to JSON and * decoding from JSON (when no charset is specified by a header) will use UTF-8. */ public static MyGsonConverterFactory create(Gson gson) { return new MyGsonConverterFactory(gson); } private final Gson gson; private MyGsonConverterFactory(Gson gson) { if (gson == null) throw new NullPointerException("gson == null"); this.gson = gson; } @Override public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { return new MyGsonResponseBodyConverter<>(gson, type); } @Override public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type)); return new MyGsonRequestBodyConverter<>(gson, adapter); } }
其实就是把源码复制下来改了改。最后,把converter改成自己的converter
new Retrofit.Builder() .baseUrl(Constants.SERVER_URL) .addConverterFactory(MyGsonConverterFactory.create()) //添加回调库,采用RxJava .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .client(genericClient()) .build();
不过这么写也有局限性,就是当使用这个converter时,所有的bean都要继承base类,
而且每当服务器改变一种结构,我们都必须修改converter
这样会相当麻烦,暂时没有想到更好的解决办法,如果有大神有更好的办法欢迎指教
本人qq184497436
相关文章推荐
- android retrofit 实战自定义converter,解决相同接口返回不同数据的问题
- android retrofit 实战自定义converter,解决相同接口返回不同数据的问题
- android retrofit 实战自定义converter,解决相同接口返回不同数据的问题
- android retrofit 实战自定义converter,解决相同接口返回不同数据的问题
- android retrofit 实战自定义converter,解决相同接口返回不同数据的问题
- Android 使用Retrofit自定义Converter解析相同接口返回不同数据
- Android 解决Retrofit请求数据,数据过多,返回json数据乱码问题
- Android解析相同接口返回不同格式json数据的方法
- jmeter解决接口返回数据乱码问题
- 解决layui中table异步数据请求不支持自定义返回数据格式的问题
- Android不同方式启动导致重复启动相同的Activity的问题解决办法(转载,解决了我的问题)
- dedecms自定义表单数据校验不对,程序返回问题解决
- spring 使用一般接口 返回数据null 的问题 解决
- 对接支付宝接口时,不使用SDK,调用成功但是返回的数据一直验签失败问题解决方案
- android自定义接口,然后在activity中实现点击监听,调用getView解决滑动错位的问题
- Xutils 使用get请求时,连续请求返回数据相同问题的解决
- Android中不同Activity之间传递自定义对象的参数问题的解决
- 转载 Android解决通过Intent调用系统拍照程序,返回图片太小的问题
- 解决通过Intent调用系统拍照程序,返回图片太小的问题[android]
- (转)jquery跨域调用webService,以及解决跨域情况下只能返回XMl格式数据的问题