一、Gson自定义TypeAdapter(已解决)
Gson序列化javabean,当list为null的时候,期望返回的是[]而不是null,比如
gson.toJson(response) = {“responseCode”:“404”,“responseMessage”:“message”,“recordDetail”:null}
这里的recordeDetail是一个list,期望返回的结果是
gson.toJson(response) = {“responseCode”:“404”,“responseMessage”:“message”,“recordDetail”:[]}
目前的解决方案:
自定义TypeAdapter,实现当list为empty的时候转成 [],但是现在自定义的writer方法并不执行,目前在研究啃源码,希望能找到解决方案
package hk.health.ehris.cdu.gson;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.util.List;
/**
* @author zhangxi
*/
@Slf4j
public class EmptyListToNullTypeAdapter extends TypeAdapter<List<?>> {
private TypeAdapter<List<?>> delegate;
public EmptyListToNullTypeAdapter(TypeAdapter<List<?>> adapter){
this.delegate = adapter;
}
// 问题出在这里,这个自定义的方法并不执行
@Override
public void write(JsonWriter out, List<?> value) throws IOException {
if (value == null || value.isEmpty()) {
out.nullValue(); // Serialize null for empty list
} else {
delegate.write(out, value);
}
}
@Override
public List<?> read(JsonReader in) throws IOException {
return delegate.read(in);
}
}
TypeAdapterFactory(解决问题的关键)
问题场景:
有个类,其中有个字段是List,希望这个list在为空的时候,序列化的结果是[],而不是null,比如这样的一个类,在序列化的时候是这样的
public class Person {
private String name;
private Integer age;
private List<Role> roleList;
}
//person = {"name":"楚子航","age":19,"roleList":[]}
原理:
自定义TypeAdapterFactory
为什么之前使用TypeAdapter的方式行不通?
TypeAdapter允许更精细地控制不同类型以及嵌套类型的序列化和反序列化过程,当你自定义一个TypeAdapter的时候,你是在处理单个特定类型的序列化和反序列化逻辑,而在自定义一个TypeAdapterFactory的时候,可以在更高的层面上控制对不同类型和嵌套类型的处理
问题描述
在序列化对象的时候,对象里面有个字段是List数组,当数组为空的时候,希望序列化后的结果是 “[]” 而不是"null".
解决方案
自定义 **TypeAdapterFactory,**在自定义的TypeAdapterFactory里面重写create()方法,在方法里实现自定义的TypeAdapter,可以实现对List数组的自定义操作
1. 自定义TypeAdapterFactory
public class NullListToEmptyFactory implements TypeAdapterFactory {
public static final NullListToEmptyFactory INSTANCE = new NullListToEmptyFactory();
private NullListToEmptyFactory(){
}
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
final Class<? super T> rawType = type.getRawType();
//Only handle List and ArrayList,let other factories handle different types
if (rawType != List.class && rawType != ArrayList.class){
return null;
}
//delegate which handles serialization of non-null values,and deserialization
final TypeAdapter<T> delegateAdapter = gson.getDelegateAdapter(this, type);
return new TypeAdapter<T>() {
@Override
public void write(JsonWriter out, T value) throws IOException {
log.info("自定义TypeAdapter开始处理空数组····");
if (value == null || ((List<?>) value).isEmpty()){
out.beginArray().endArray();
} else {
delegateAdapter.write(out,value);
}
}
@Override
public T read(JsonReader in) throws IOException {
return delegateAdapter.read(in);
}
};
}
}
2. 使用GsonBuilder注册该工厂
Gson gson = new GsonBuilder()
.serializeNulls()
.registerTypeAdapterFactory(NullListToEmptyFactory.INSTANCE)
.create();
gson.toJson(YourObject);
注册进去之后,由于Gson序列化时会首先去查找自定义的TypeAdapter,然后再去查找默认的,最后使用反射生成一个包含该类所有类型的序列化实例,进行序列化。
打印结果:
person = {“name”:“楚子航”,“age”:19,“roleList”:[]}
这里显示的是"[]",而不是“null”
TypeAdapter允许更精细地控制不同类型以及嵌套类型的序列化和反序列化过程,当你自定义一个TypeAdapter的时候,你是在处理单个特定类型的序列化和反序列化逻辑,而在自定义一个TypeAdapterFactory的时候,可以在更高的层面上控制对不同类型和嵌套类型的处理