最近的项目中遇到过 前端的实体中定义的类型,经常与后端对不上
比如字段属性为 float,结果返回 “”;
这种类型对应不上的解析,Gson会抛出错误,整个解析全跪;
目前的需求是想提高解析的容错性,(至少ios在这个方面是第三方框架很好的容错机制)
经过百度后,发现了Gson的健壮性,是可以扩展了。
## 探索1 ##
TypeAdapter
public abstract class TypeAdapter {
public abstract void write(JsonWriter out, T value) throws IOException;
public abstract T read(JsonReader in) throws IOException;
}
通过Gson gson = new GsonBuilder().registerTypeAdapter(XXX.class, new XXXAdapter()) .create();
添加adapter
或者Gson1.0中的【JsonSerializer与JsonDeserializer】
Gson gson = new GsonBuilder()
.registerTypeAdapter(Integer.class, new JsonDeserializer() {
@Override
public Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
try {
return json.getAsInt();
} catch (NumberFormatException e) {
return -1;
}
}
})
.create();
JsonSerializer<Number> numberJsonSerializer = new JsonSerializer<Number>() {
@Override
public JsonElement serialize(Number src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(String.valueOf(src));
}
};
—这种方式可以解决的是 以下的解析问题:
System.out.println(gson.toJson(100)); //结果:100
System.out.println(gson.fromJson(“\”\”“, Integer.class)); //结果-1
如果是复杂的实体类型,是无法满足的。
继续
探索2
灵感来源【https://www.jianshu.com/p/c6dd9a6b10ee】
以上连接解决的问题是 null转为”“;
我的需求是 float 遇到“”,可以赋值为默认值 -1;
以下是我的解决方案
public class FloatlNullAdapter extends TypeAdapter<Float> {
@Override
public Float read(JsonReader reader) throws IOException {
// TODO Auto-generated method stub
if (reader.peek() == JsonToken.STRING) {
reader.skipValue(); //跳过当前
return -1f;
}
BigDecimal bigDecimal = new BigDecimal(reader.nextString());
return bigDecimal.floatValue();
}
@Override
public void write(JsonWriter writer, Float value) throws IOException {
// TODO Auto-generated method stub
writer.value(value);
}
}
reader.skipValue(); 是一个关键的地方,当前的value 并不是我们要的类型,继续解析会报错,所以需要跳过去
以上折腾可以满足当前的需求了。
其他类型的容错也是可以自己写,
通过
public class MyTypeAdapterFactory<T> implements TypeAdapterFactory {
@SuppressWarnings("unchecked")
public TypeAdapter create(Gson gson, TypeToken type) {
Class rawType = (Class) type.getRawType();
if (rawType == BigDecimal.class) {
return (TypeAdapter) new BigDecimalNullAdapter();
} else if (rawType == Float.class || rawType == float.class) {
return (TypeAdapter) new FloatlNullAdapter();
}
return null;
}
}
上图代码中 if()添加对应的类型+adaoter
测试代码如下
try {
String json = "{\"price\":\"\",\"value\":2.12,\"type\":\"3\"}";
Gson gson = new GsonBuilder().registerTypeAdapterFactory(new MyTypeAdapterFactory()).create();
price = gson.fromJson(json, Price.class);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (price != null) {
Log.d("bsnl", "11");
} else {
Log.d("bsnl", "22");
}
}
public class Price {
public float value;
public float type;
public float price;
}
修改对应的json中数据达到测试效果
小菜鸟一只,如果有什么理解不对,误人子弟的地方,烦请指出。