Gson自定义适配器处理特殊解析异常
2016-09-26 15:17
363 查看
Gson自定义适配器
学习github项目中遇到了特殊的解析出错的问题,查了好久,最后是需要自定义适配器,以前没用过这东西:(以下内容只是方便自己记忆,不做其他用途)参考:http://www.jianshu.com/p/3108f1e44155目录
Gson自定义适配器目录
什么时候会用到这个
TypeAdapter
JsonSerializer与JsonDeserializer
registerTypeAdapter与registerTypeHierarchyAdapter
自己解决的问题使用retrofit解析网络访问以下是回调处理MatchPlayerInfo字段本该返回对象却返回空字符串引起的问题腾讯NBA的Json的坑
什么时候会用到这个?
1、本来解析字符串 “24” 转成int 的24,但如果有些情况下给你返了个空字符串,实际上我们需要把空字符串转成一个固定的值-12、本来是解析一个对象,但是后台直接传回来一个null(这表示整个对象是null,正常一般后台会new一个空对象给你)
3、服务器返回的数据中data字段类型不固定,比如请求成功data是一个List,不成功的时候是String类型,这样前端在使用泛型解析的时候
TypeAdapter
Gson2.0开始提供的抽象类,两个主要的方法public abstract class TypeAdapter<T> { public abstract void write(JsonWriter out, T value) throws IOException; public abstract T read(JsonReader in) throws IOException; }
一般与GsonBuilder.registerTypeAdapter 示或GsonBuilder.registerTypeHierarchyAdapter配合使用
使用实例:
User user = new User("张三", 20); user.idnum = "342401199108165674"; Gson gson = new GsonBuilder() //为User注册TypeAdapter .registerTypeAdapter(User.class, new UserTypeAdapter()) .create(); System.out.println(gson.toJson(user)); public class UserTypeAdapter extends TypeAdapter<User> { @Override public void write(JsonWriter out, User value) throws IOException { out.beginObject(); out.name("name").value(value.name); out.name("age").value(value.age); out.name("idnum").value(value.idnumm); out.endObject(); } @Override public User read(JsonReader in) throws IOException { User user = new User(); in.beginObject(); while (in.hasNext()) { switch (in.nextName()) { case "name": user.name = in.nextString(); break; case "age": user.age = in.nextInt(); break; case "idnum": user.idnum = in.nextString(); break; } } in.endObject(); return user; } }
注意:用过自定义适配器之后,注解就失效了比如:@SerializedName
针对问题一:
Gson gson = new GsonBuilder() .registerTypeAdapter(Integer.class, new TypeAdapter<Integer>() { @Override public void write(JsonWriter out, Integer value) throws IOException { out.value(String.valueOf(value)); } @Override public Integer read(JsonReader in) throws IOException { try { return Integer.parseInt(in.nextString()); } catch (NumberFormatException e) { return -1; } } }) .create();
JsonSerializer与JsonDeserializer
JsonSerializer(序列化,其实就是toJson)与JsonDeserializer(反序列化,其实就是转化为对象),把TypeAdapter的功能细化序列化:
JsonSerializer<Number> numberJsonSerializer = new JsonSerializer<Number>() { @Override public JsonElement serialize(Number src, Type typeOfSrc, JsonSerializationContext context) { return new JsonPrimitive(String.valueOf(src)); } }; Gson gson = new GsonBuilder() .registerTypeAdapter(Integer.class, numberJsonSerializer)
反序列化:
Gson gson = new GsonBuilder() .registerTypeAdapter(Integer.class, new JsonDeserializer<Integer>() { @Override public Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { try { return json.getAsInt(); } catch (NumberFormatException e) { return -1; } } }) .create();
registerTypeAdapter与registerTypeHierarchyAdapter
registerTypeAdapter支持泛型,registerTypeHierarchyAdapter支持继承泛型:
Type type = new TypeToken<List<User>>() {}.getType(); TypeAdapter typeAdapter = new TypeAdapter<List<User>>() { //略 }; Gson gson = new GsonBuilder() .registerTypeAdapter(type, typeAdapter) .create(); List<User> list = new ArrayList<>(); list.add(new User("a",11)); list.add(new User("b",22));
继承:
JsonSerializer<Number> numberJsonSerializer = new JsonSerializer<Number>() { @Override public JsonElement serialize(Number src, Type typeOfSrc, JsonSerializationContext context) { return new JsonPrimitive(String.valueOf(src)); } }; Gson gson = new GsonBuilder().registerTypeHierarchyAdapter(Number.class, numberJsonSerializer) .create();
解决问题三:
方法一:
Gson gson = new GsonBuilder().registerTypeHierarchyAdapter(List.class, new JsonDeserializer<List<?>>() { @Override public List<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { if (json.isJsonArray()){ //这里要自己负责解析了 Gson newGson = new Gson(); return newGson.fromJson(json,typeOfT); }else { //和接口类型不符,返回空List return Collections.EMPTY_LIST; } } }).create();
方法二:(效率高)
Gson gson = new GsonBuilder().registerTypeHierarchyAdapter(List.class, new JsonDeserializer<List<?>>() { @Override public List<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { if (json.isJsonArray()) { JsonArray array = json.getAsJsonArray(); //获取泛型的实际类型 Type itemType = ((ParameterizedType) typeOfT).getActualTypeArguments()[0]; List list = new ArrayList<>(); for (int i = 0; i < array.size(); i++) { JsonElement element = array.get(i); Object item = context.deserialize(element, itemType); list.add(item); } return list; } else { //和接口类型不符,返回空List return Collections.EMPTY_LIST; } } }).create();
自己解决的问题(使用retrofit解析网络访问,以下是回调),处理MatchPlayerInfo字段本该返回对象,却返回空字符串引起的问题(腾讯NBA的Json的坑)
Call<String> call = api.getMatchCalendar(teamId, year, month); call.enqueue(new retrofit2.Callback<String>() { @Override public void onResponse(Call<String> call, retrofit2.Response<String> response) { if (response != null && !TextUtils.isEmpty(response.body())) { String jsonStr = response.body(); //主要在这 MatchCalendar match = JsonParser.parseWithGson(MatchCalendar.class, jsonStr); cbk.onSuccess(match); cache.put(key, match); LogUtils.i("resp:" + jsonStr); } else { cbk.onFailure("获取数据失败"); } } @Override public void onFailure(Call<String> call, Throwable t) { cbk.onFailure(t.getMessage()); } });
public class JsonParser { static Gson gson = new GsonBuilder().serializeNulls() //自定义类型适配器 .registerTypeAdapter(MatchPlayerInfo.class, new MatchPlayerInfoDefaultAdapter()) .registerTypeHierarchyAdapter(List.class, new ListDefaultAdapter()) .create(); public static <T> T parseWithGson(Class<T> classOfT, String jsonStr) { return gson.fromJson(jsonStr, classOfT); } }
public class MatchPlayerInfoDefaultAdapter implements JsonSerializer<MatchPlayerInfo>, JsonDeserializer<MatchPlayerInfo> { @Override public MatchPlayerInfo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { try { //处理空字符串 if (json.getAsString().equals("")) { return null; //return new MatchPlayerInfo(); } } catch (Exception ignore) { } try { return new Gson().fromJson(json, MatchPlayerInfo.class); } catch (NumberFormatException e) { throw new JsonSyntaxException(e); } } @Override public JsonElement serialize(MatchPlayerInfo src, Type typeOfSrc, JsonSerializationContext context) { final JsonObject jsonObject = new JsonObject(); Class<?> clz = src.getClass(); Field[] fields = clz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); try { jsonObject.addProperty(field.getName(), (String) field.get(src)); } catch (IllegalAccessException e) { e.printStackTrace(); } } return jsonObject; } }
相关文章推荐
- [原创]Enterprise Library深入解析与灵活应用(4):创建一个自定义Exception Handler改变ELAB的异常处理机制
- Gson&FastJson解析异常Json的处理
- Gson解析空字符串发生异常的处理方法
- 解析自定义头像、链接、处理微博上类似 “@” 和 “#” 的特殊转义字符并在UIWebView显示的例子
- Gson解析空字符串异常的处理
- Gson解析空字符串异常的处理
- Json转换利器Gson之实例五-实际开发中的特殊需求处理(手动解析-TypeToken)
- Gson解析(5)——实际开发中的特殊需求处理
- 如何构建一个比较好的自定义异常处理模型?
- Java程序异常处理的特殊情况
- ASP.NET AJAX入门系列(8):自定义异常处理
- java异常处理之自定义异常类
- ASP.NET AJAX入门系列(8):自定义异常处理
- ASP.NET AJAX入门系列(8):自定义异常处理
- 自定义异常处理的功能实现
- ASP.NET AJAX入门系列(8):自定义异常处理
- 利用自定义的异常处理重起你的应用程序(续)
- ASP.NET AJAX入门系列(8):自定义异常处理
- ASP.NET AJAX入门系列(8):自定义异常处理
- ASP.NET AJAX入门系列(8):自定义异常处理