- 有时候我们需要对基本类型做一些转换,比如我们需要将接口传回的null转换为空字符串,避免空指针异常,我们可以这样做:
/**
* 自定义TypeAdapter ,null对象将被解析成空字符串
*/
public static final TypeAdapter<String> STRING = new TypeAdapter<String>() {
public String read(JsonReader reader) {
try {
if (reader.peek() == JsonToken.NULL) {
reader.nextNull();
return "";//原先是返回Null,这里改为返回空字符串
}
return reader.nextString();
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
public void write(JsonWriter writer, String value) {
try {
if (value == null) {
writer.nullValue();
return;
}
writer.value(value);
} catch (Exception e) {
e.printStackTrace();
}
}
};
- 有时候我们需要对接口返回的数据中的某个字段进行变换,我们可以实现JsonDeserializer接口来自定义反序列化过程:
private static final JsonDeserializer APPLE = new JsonDeserializer<Apple>() {
@Override
public Apple deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
Apple apple = new Gson().fromJson(json, typeOfT);
apple.setName("newApple");
return apple;
}
};
- 有时候项目中会遇到这样的场景:接口返回来的数据结构是变化的,我们不能直接指定class,这样我们可以使用下面这个方法:
/**
* Creates a new runtime type adapter using for {@code baseType} using {@code
* typeFieldName} as the type field name. Type field names are case sensitive.
*/
public static <T> RuntimeTypeAdapterFactory<T> of(Class<T> baseType, String typeFieldName) {
return new RuntimeTypeAdapterFactory<T>(baseType, typeFieldName);
}
第一个参数是类的Class,第二个参数是用来区分使用哪个class的字段
举一个栗子:
private static final RuntimeTypeAdapterFactory<PayOrder> PAY_ORDER_RUNTIME_TYPE_ADAPTER_FACTORY = RuntimeTypeAdapterFactory
.of(Fruit.class, "name")
.registerSubtype(Apple.class, "apple")
.registerSubtype(Orange.class, "orange");
在Fruit、Apple、Orange里面加上只有name字段的构造函数,然后在Apple里面调用Fruit("apple"),在Orange里面调用Fruit("orange"),这样可以实现根据name转换为不同的class了。当然,还要在GsonBuilder中调用registerTypeAdapterFactory注册该factory。
写于2018-4-26
网友评论