Gson自定义适配器处理特殊解析异常
来源:互联网 发布:java acos函数 编辑:程序博客网 时间:2024/05/26 15:56
Gson自定义适配器
学习github项目中遇到了特殊的解析出错的问题,查了好久,最后是需要自定义适配器,以前没用过这东西:(以下内容只是方便自己记忆,不做其他用途)参考:http://www.jianshu.com/p/3108f1e44155
目录
- Gson自定义适配器
- 目录
- 什么时候会用到这个
- TypeAdapter
- JsonSerializer与JsonDeserializer
- registerTypeAdapter与registerTypeHierarchyAdapter
- 自己解决的问题使用retrofit解析网络访问以下是回调处理MatchPlayerInfo字段本该返回对象却返回空字符串引起的问题腾讯NBA的Json的坑
什么时候会用到这个?
1、本来解析字符串 “24” 转成int 的24,但如果有些情况下给你返了个空字符串,实际上我们需要把空字符串转成一个固定的值-1
2、本来是解析一个对象,但是后台直接传回来一个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; }}
0 0
- Gson自定义适配器处理特殊解析异常
- Gson解析空字符串异常的处理
- Gson&FastJson解析异常Json的处理
- 自定义GSON类型适配器
- gson自定义适配器
- Gson特殊字段解析
- Gson字段特殊处理
- Json转换利器Gson之-实际开发中的特殊需求处理(手动解析-TypeToken处理)
- 自定义类型适配器的Gson工具类
- Gson解析(5)——实际开发中的特殊需求处理
- Json转换利器Gson之实例五-实际开发中的特殊需求处理(手动解析-TypeToken)
- 异常处理+异常+处理异常+自定义异常
- Gson 基础教程 —— 自定义类型适配器(TypeAdapter)
- NoSuchMethodError异常处理之特殊处理方式
- Gson-----8、实际开发中的特殊需求处理
- 关于Gson解析关键字处理问题
- Google的GSON处理JSON解析
- Java异常处理-----自定义异常
- 温故知新(九):php错误处理机制
- 第四周项目-长方形面积
- rapror程序:我的第一个分段函数(y=x-1(x>=1);y=-x+1(x<1))
- .NET CORE 实践(3)--Visual Studio 2015 Update 3更新之后DotNetCore.1.0.1-VS2015Tools.Preview2.0.2.exe无法正确安装
- avoid zombie
- Gson自定义适配器处理特殊解析异常
- studio添加注释模板
- Hbase修改表名
- HDU5519 Kykneion asma (指数生成函数+快速数论变换模任意数+启发式合并思想)
- c# - Resolve<T> to create instance
- 使用Fresco出现的问题
- [iOS AppStore] 根据AppStore中的App版本 做跟新提示
- Java 之 JDK 的下载,安装,及Java环境配置教程(一)
- IOS 利用UIScrollView实现无限轮播图