Gson特殊用法
原创
©著作权归作者所有:来自51CTO博客作者钰娘娘ynn的原创作品,请联系作者获取转载授权,否则将追究法律责任
正常用法:
Gson gson = new Gson();
Object obj = gson.fromJson(str,Object.class);String gsonStr = gson.toJson(obj);
就这样,就可以了。
但是有些特殊情况,可能要特殊处理,这里先说一些正常的,非服务器错误的情况:
(1)数字类型返回null
处理方法1:
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();
System.out.println(gson.toJson(100)); //结果:100
System.out.println(gson.fromJson("\"\"", Integer.class)); //结果-1
或,处理方法2:
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();
System.out.println(gson.toJson(100)); // 结果:"100"
System.out.println(gson.fromJson("\"\"",Integer.class)); // 结果:-1
registerTypeAdapter这个方法个人理解为拦截,对序列化,反序列化,gson读写等拦截,
其中:
TypeAdapter:拦截全部,万用,所有处理可放在这里
JsonSerializer:拦截序列化过程
JsonDeserializer:拦截反序列化过程
另外,服务器可能不返回空字段,如服务器在不具备某字段(为空时不返回){“a”:”1”,”b”:”2”}当b为空时服务器返回{“a”:”1”},这种情况需要加serializeNulls()这种情况的处理:
.registerTypeAdapter(XX.class, new XXAdapter())
子类全部处理:registerTypeHierarchyAdapter
泛型类使用typeAdapter(可以通过用JsonSerializer和JsonDeserializer避免):
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));
//注意,多了个type参数
String result = gson.toJson(list, type);
服务器返回为空时为”“
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
好感谢公司的后台程序员,没给android传数据带来什么大麻烦。其实如果服务器返回数据正常,一直用一种类型,且没有json错误,为空时返回正常,android端是基本不用处理的。但不保证用第三方的时候,返回数据一直正常无误,所以特别记录下。
附:空值预防(http://www.jianshu.com/p/c6dd9a6b10ee):
public class XXAdapter extends TypeAdapter<String> {
@Override
public String read(JsonReader reader) throws IOException {
// TODO Auto-generated method stub
if (reader.peek() == JsonToken.NULL) {
reader.nextNull();
return "";
}
return reader.nextString();
}
@Override
public void write(JsonWriter writer, String value) throws IOException {
// TODO Auto-generated method stub
if (value == null) {
writer.nullValue();
return;
}
writer.value(value);
}
}