簡介
前段時間在換成gson 重寫下解析遇到一些問題,之前是使用JSONObject 進行解析,在使用GSON 之後發現解析數據錯誤和獲取不到值得問題。
後臺格式不規範
例如:
有值時返回:{ person:{"name":"wang",age=17} }
有沒有值時返回:
{ person:[] }
這個時候用gson就會拋出解析異常。
解決方案:(使用 TypeAdapterFactory)
final static class SafeTypeAdapterFactory implements TypeAdapterFactory{
@Override
public TypeAdapter create(Gson gson, final TypeToken type) {
final TypeAdapter delegate = gson.getDelegateAdapter(this,type);
return new TypeAdapter() {
@Override
public void write(JsonWriter out, T value) throws IOException {
try {
delegate.write(out, value);
} catch (IOException e) {
delegate.write(out, null);
}
}
@Override
public T read(JsonReader in) throws IOException {
try {
return delegate.read(in);
} catch (IOException e) {
in.skipValue();
return null;
} catch (IllegalStateException e) {
in.skipValue();
return null;
} catch (JsonSyntaxException e) {
in.skipValue();
if(type.getType() instanceof Class){
try {
return (T) ((Class)type.getType()).newInstance();
} catch (Exception e1) {
}
}
return null;
}
}
};
}
}
使用GSON 時:
Gson myGson = new GsonBuilder().registerTypeAdapterFactory(new SafeTypeAdapterFactory()).create();
例如解析下面這樣的bean:
class Bean{
Inner in;
String a;
String b;
class Inner{
String c;
}
}
返回的Bean 就會是 in = new Inner();
其他的異常就會賦值爲null,具體可以根據自己需要修改。
2. 解析bool 類型時服務器有兩個寫法:第一種 True 或者 False ,第二種 0 代表 False 1 代表 True。
我在bean 中都使用 boolean 來表示該值
解決方案:(使用TypeAdapter)
Gson myGson = new GsonBuilder()
.registerTypeAdapter(boolean.class, new JsonDeserializer<Boolean>() {
@Override
public Boolean deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
try {
return json.getAsInt() == 1;
}catch (NumberFormatException e){
return json.getAsBoolean();
}
}
}).create();
3.對於bean 中有部分屬性需要忽略
解決方案:(使用ExclusionStrategy)
創建註解類 Exclude
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Exclude {
}
在gson中配置 忽略帶有Exclude的屬性:
Gson gson = new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy(){
@Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getAnnotation(Exclude.class) != null;
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
})
使用時在需要忽略的屬性上標記@Exclude 即可:
class Mock{
String name;
String age;
@Exclude
String gender;
}
參考
[1]:http://stackoverflow.com/questions/4802887/gson-how-to-exclude-specific-fields-from-serialization-without-annotations .
[2]:http://stackoverflow.com/questions/10596667/how-to-invoke-default-deserialize-with-gson .