Retrofit实战之json反序列化的那些事
来源:互联网 发布:最新淘宝我是卖家在哪 编辑:程序博客网 时间:2024/06/05 15:35
Retrofit实战之json反序列化的那些事
retrofit是一个十分优秀的网络框架,它为了我们封装了很多内容,使我们请求十分方便,获取也十分轻松,对于返回的json可以轻松的用gson自动解析。但是在这个方便的后面,也带来了一些小小的隐患。
下面就有两种情况,在json被反序列化时,给我们在这个炎热的夏天里造成了蛋蛋的凉意。
接口请求失败,可它还是要全部反序列化
一般来说接口返回的形式包括:返回码,信息,返回数据这三部分,大致如下:
{ statusCode: "200", statusMessage: "回传成功", data: { //内容 }}
而网络请求时,也会创建一个Response范型类,作为请求结果的映射。
public class Response <T>{ private int statusCode; private String statusMessage; private T data; public int getStatusCode() { return statusCode; } public void setStatusCode(int statusCode) { this.statusCode = statusCode; } public String getStatusMessage() { return statusMessage; } public void setStatusMessage(String statusMessage) { this.statusMessage = statusMessage; } public T getData() { return data; } public void setData(T data) { this.data = data; }}
当接口请求失败或者返回的数据错误(也就是返回码是错误码时),按照常理,我们是不会解析data的。可gson每次都会对json进行反序列化,不管json里面的数据是否是成功的,里面的data都会被反序列化。这个就有些忧伤了,我们不是应该只对成功的请求才反序列化json里面的data数据吗?
接口返回数据形式不一致
我司的接口就有这个蛋疼的问题,失败时统一返回的格式是下面这种:
{ statusCode: "103", statusMessage: "请求失败", data: []
只要请求失败,不管data里面的数据是JSONObject 还是JSONArray,都返回JSONArray。这就蛋疼了,经常会有json解析的异常抛出,于是我不得不含泪解决。
解决方法
基于上面的2个需求,我们得找出解决方法。由于我用retrofit都是用gson解析,所以解决这个问题的方法用的是gson特性。然后再思考一下问题的本质,其实就是它在不该反序列化的地方反序列化,导致了出错。所以我们只要找到自定义反序列化的方法就行了。
我相信很多人都用过gson,但是你真的了解它吗,其实它是很强大的,是吧,皮卡丘。对于gson不熟悉的,可以看看下面文章 你真的会用Gson吗?Gson使用指南。
一般gson进行对象化映射都有两个步骤,第一步,getTypeAdapter(),第二步,read()反序列化。这在retrofit的GsonResponseBodyConverter源码中清晰可见:
//为了方便观看,我对代码进行了一些修改public T convert(ResponseBody value) throws IOException { TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type)); JsonReader jsonReader = gson.newJsonReader(value.charStream()); try { return adapter.read(jsonReader); } finally { value.close(); } }}
对于TypeAdapter我们是可以自定义的,由于这里我们只需要反序列化,所以我们只用实现JsonDeserializer,并指定需要处理的类型就可以了,具体代码如下。
public class ResultJsonDeser implements JsonDeserializer<Response<?>> { @Override public Response<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { Response response = new Response(); if (json.isJsonObject()){ JsonObject jsonObject = json.getAsJsonObject(); int code = jsonObject.get("statusCode").getAsInt(); response.setStatusCode(code); response.setStatusMessage(jsonObject.get("statusMessage").getAsString()); if (code != 200){ return response; } Type itemType = ((ParameterizedType) typeOfT).getActualTypeArguments()[0]; response.setData(context.deserialize(jsonObject.get("data"), itemType)); return response; } return response; }}
最后将ResultJsonDeser在gson中注册,我们就可以愉快的玩耍,不用担心那些格式的问题了。
Gson gson = new GsonBuilder() .registerTypeHierarchyAdapter(Response.class, new ResultJsonDeser()) .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") .create();
当然,最后的最后,还是需要将gson加入retrofit中的,addConverterFactory(GsonConverterFactory.create(gson))
。相信大家,对于这类问题都有一些思路了,对于retrofit的使用也能更加得劲了。
- Retrofit实战之json反序列化的那些事
- [HTTP那些事]JSON反序列化
- json的反序列化
- json 反序列化
- Json反序列化
- json反序列化
- json反序列化
- 反序列化Json
- JSON反序列化的方法
- Android Json数据的反序列化
- json数组的反序列化
- json多层数组的反序列化
- ios-day21-02(ios开发之json数据的解析(json的反序列化))
- ios-day23-02(ios开发之json的反序列化、提交json数据到服务器)
- Json反序列化之ObjectMapper(自定义实现反序列化方法)
- Android实战——之反序列化实例
- JSON反序列化异常
- JSON高效反序列化
- iOS常用功能的网站地址
- GDataXMLNode使用
- 几个关于jsp的问题
- 属性大全
- spring4.x hibernate4.x 整合 ehcache 注解 annotate
- Retrofit实战之json反序列化的那些事
- 分解质因数-week6-C语言习题集
- ArcGIS教程:自定义地图范围(二)
- java 二进制的问题
- buildroot的使用简介
- 手把手搭建一个聊天机器人(二)
- OSX Install Cocopods
- JVM垃圾回收机制总结:调优方法
- 成员方发的分类