Gson提供了丰富的预定义类型适配器,在对象和JSON串之间进行序列化和反序列化时,指定对象和字符串之间的转换方式,
DateTypeAdapter
public final class DateTypeAdapter extends TypeAdapter<Date> {
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
return typeToken.getRawType() == Date.class ? (TypeAdapter<T>) new DateTypeAdapter() : null;
}
};
private final DateFormat enUsFormat
= DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US);//美国Locale
private final DateFormat localFormat
= DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT);//本地Locale
private final DateFormat iso8601Format = buildIso8601Format();//ISO8601时间格式
private static DateFormat buildIso8601Format() {//构造(ISO8601DateFormat
DateFormat iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC"));
return iso8601Format;
}
@Override public Date read(JsonReader in) throws IOException {//JsonReader中包含着要转换为Date的字符串
if (in.peek() == JsonToken.NULL) {//如果字符串为null
in.nextNull();//将这个null消费完
return null;
}
return deserializeToDate(in.nextString());//将字符串反序列化为日期对象
}
private synchronized Date deserializeToDate(String json) {
try {
return localFormat.parse(json);//首先尝试本地Locale
} catch (ParseException ignored) {
}
try {
return enUsFormat.parse(json);//再次尝试美国英语Locale
} catch (ParseException ignored) {
}
try {
return iso8601Format.parse(json); //最后尝试ISO8601时间格式
} catch (ParseException e) {
throw new JsonSyntaxException(json, e);
}
}
@Override public synchronized void write(JsonWriter out, Date value) throws IOException {
if (value == null) {
out.nullValue();//设置null值
return;
}
String dateFormatAsString = enUsFormat.format(value);//直接使用美国英语Locale将Date转换成为字符串
out.value(dateFormatAsString);
}
}
ArrayTypeAdapter
public final class ArrayTypeAdapter<E> extends TypeAdapter<Object> {//为什么是Object而不是E
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
@SuppressWarnings({"unchecked", "rawtypes"})
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
Type type = typeToken.getType();
//如果type不是Array,返回null
if (!(type instanceof GenericArrayType || type instanceof Class && ((Class<?>) type).isArray())) {
return null;
}
Type componentType = $Gson$Types.getArrayComponentType(type);
TypeAdapter<?> componentTypeAdapter = gson.getAdapter(TypeToken.get(componentType));
return new ArrayTypeAdapter(
gson, componentTypeAdapter, $Gson$Types.getRawType(componentType));
}
};
private final Class<E> componentType;
private final TypeAdapter<E> componentTypeAdapter;
public ArrayTypeAdapter(Gson context, TypeAdapter<E> componentTypeAdapter, Class<E> componentType) {
this.componentTypeAdapter =
new TypeAdapterRuntimeTypeWrapper<E>(context, componentTypeAdapter, componentType);
this.componentType = componentType;
}
public Object read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
List<E> list = new ArrayList<E>();
in.beginArray();//开始读数组
while (in.hasNext()) {
E instance = componentTypeAdapter.read(in);
list.add(instance);
}
in.endArray();//读数组结束
Object array = Array.newInstance(componentType, list.size());
for (int i = 0; i < list.size(); i++) {
Array.set(array, i, list.get(i));
}
return array;
}
@SuppressWarnings("unchecked")
@Override public void write(JsonWriter out, Object array) throws IOException {
if (array == null) {
out.nullValue();
return;
}
out.beginArray();
for (int i = 0, length = Array.getLength(array); i < length; i++) {
E value = (E) Array.get(array, i);
componentTypeAdapter.write(out, value);
}
out.endArray();
}
}
看到ArrayTypeAdapter的实现,可以说有点晕菜了,原因是对泛型不熟悉了,回头再看看泛型吧!!
SqlDateTypeAdapter
public final class SqlDateTypeAdapter extends TypeAdapter<java.sql.Date> {
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {//这个FACTORY干啥用的?
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
return typeToken.getRawType() == java.sql.Date.class
? (TypeAdapter<T>) new SqlDateTypeAdapter() : null;
}
};
private final DateFormat format = new SimpleDateFormat("MMM d, yyyy"); //java.sql.Date与字符串转换的DateFormat
@Override
public synchronized java.sql.Date read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
try {
final long utilDate = format.parse(in.nextString()).getTime();
return new java.sql.Date(utilDate);
} catch (ParseException e) {
throw new JsonSyntaxException(e);
}
}
@Override
public synchronized void write(JsonWriter out, java.sql.Date value) throws IOException {
out.value(value == null ? null : format.format(value));//将java.sql.Date对象转换成字符串,例如"Aug 13, 2014",所以默认的java.sql.Date转换为年月日
}
}
ObjectTypeAdapter
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.internal.LinkedTreeMap;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Adapts types whose static type is only 'Object'. Uses getClass() on
* serialization and a primitive/Map/List on deserialization.
*/
public final class ObjectTypeAdapter extends TypeAdapter<Object> {
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
@SuppressWarnings("unchecked")
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (type.getRawType() == Object.class) { //
return (TypeAdapter<T>) new ObjectTypeAdapter(gson);
}
return null;
}
};
private final Gson gson;
private ObjectTypeAdapter(Gson gson) {
this.gson = gson;
}
@Override public Object read(JsonReader in) throws IOException {
JsonToken token = in.peek();//判断字符串的实际类型
switch (token) {
case BEGIN_ARRAY://如果是Array或者Map或者List,解析为ArrayList
List<Object> list = new ArrayList<Object>();
in.beginArray();
while (in.hasNext()) {
list.add(read(in));
}
in.endArray();
return list;
case BEGIN_OBJECT: //如果是Object,那么解析为Map,Map为String和Object的映射
Map<String, Object> map = new LinkedTreeMap<String, Object>();
in.beginObject();
while (in.hasNext()) {
map.put(in.nextName(), read(in));
}
in.endObject();
return map;
case STRING://如果是字符串类型
return in.nextString();
case NUMBER://如果是数字类型
return in.nextDouble();
case BOOLEAN://如果是布尔类型
return in.nextBoolean();
case NULL://如果是Null
in.nextNull();
return null;
default:
throw new IllegalStateException();
}
}
@SuppressWarnings("unchecked")
@Override public void write(JsonWriter out, Object value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
TypeAdapter<Object> typeAdapter = (TypeAdapter<Object>) gson.getAdapter(value.getClass());//得到value的实际类型对应的TypeAdapter
if (typeAdapter instanceof ObjectTypeAdapter) {//因为是Object,没有数据字段可以写
out.beginObject();
out.endObject();
return;
}
typeAdapter.write(out, value);//调用实际的TypeAdapter进行写操作
}
}
说明:下面的代码片段没有使用上面的ObjectTypeAdapter进行转换那么ObjectTypeAdapter究竟如何使用??
Map<String, String> map = new HashMap<String, String>();
map.put("IM1","QQ");
map.put("IM2","MSN");
Object obj = map;
str = new Gson().toJson(obj);
System.out.println(str);//{"IM2":"MSN","IM1":"QQ"}
obj = new Integer(100);
str = new Gson().toJson(obj);
System.out.println(str);//100
obj = new Boolean(true);
str = new Gson().toJson(obj);
System.out.println(str);//true
常用数据类型适配器
如下的代码,对单个的obj进行序列化,得到的字符串是100,也能将"100"反序列化为Integer对象,这里并没有JSON串的格式,但是却实现了序列化和反序列化
Integer obj = new Integer(100);
str = new Gson().toJson(obj);
System.out.println(str);//100
obj = new Gson().fromJson(str,Integer.class); //obj是100
将基本数据类型的数据序列化为普通字符串,普通字符串序列化为基本数据类型,这是如何做到的呢?Gson在TypeAdapters中定义了一系列的简单数据类型的类型适配器,
Integer/Long/Short/Boolean/String/BigDecimal/BitSet/Byte/Double/Float/InetAddress/Locale/StringBuffer/StringBuilder/Timestamp/URI/URL/Enum
默认的Gson对象内置了哪些类型适配器
Gson构造方法表明默认的Gson对象已经将上面提到的预定义类型适配器参加到Gson对象中
public Gson() {
this(Excluder.DEFAULT, FieldNamingPolicy.IDENTITY,
Collections.<Type, InstanceCreator<?>>emptyMap(), false, false, DEFAULT_JSON_NON_EXECUTABLE,
true, false, false, LongSerializationPolicy.DEFAULT,
Collections.<TypeAdapterFactory>emptyList());
}
Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingPolicy,
final Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
boolean prettyPrinting, boolean serializeSpecialFloatingPointValues,
LongSerializationPolicy longSerializationPolicy,
List<TypeAdapterFactory> typeAdapterFactories) {
this.constructorConstructor = new ConstructorConstructor(instanceCreators);
this.serializeNulls = serializeNulls;
this.generateNonExecutableJson = generateNonExecutableGson;
this.htmlSafe = htmlSafe;
this.prettyPrinting = prettyPrinting;
List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();
// built-in type adapters that cannot be overridden
factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
factories.add(ObjectTypeAdapter.FACTORY);
// the excluder must precede all adapters that handle user-defined types
factories.add(excluder);
// user's type adapters
factories.addAll(typeAdapterFactories);
// type adapters for basic platform types
factories.add(TypeAdapters.STRING_FACTORY);
factories.add(TypeAdapters.INTEGER_FACTORY);
factories.add(TypeAdapters.BOOLEAN_FACTORY);
factories.add(TypeAdapters.BYTE_FACTORY);
factories.add(TypeAdapters.SHORT_FACTORY);
factories.add(TypeAdapters.newFactory(long.class, Long.class,
longAdapter(longSerializationPolicy)));
factories.add(TypeAdapters.newFactory(double.class, Double.class,
doubleAdapter(serializeSpecialFloatingPointValues)));
factories.add(TypeAdapters.newFactory(float.class, Float.class,
floatAdapter(serializeSpecialFloatingPointValues)));
factories.add(TypeAdapters.NUMBER_FACTORY);
factories.add(TypeAdapters.CHARACTER_FACTORY);
factories.add(TypeAdapters.STRING_BUILDER_FACTORY);
factories.add(TypeAdapters.STRING_BUFFER_FACTORY);
factories.add(TypeAdapters.newFactory(BigDecimal.class, TypeAdapters.BIG_DECIMAL));
factories.add(TypeAdapters.newFactory(BigInteger.class, TypeAdapters.BIG_INTEGER));
factories.add(TypeAdapters.URL_FACTORY);
factories.add(TypeAdapters.URI_FACTORY);
factories.add(TypeAdapters.UUID_FACTORY);
factories.add(TypeAdapters.LOCALE_FACTORY);
factories.add(TypeAdapters.INET_ADDRESS_FACTORY);
factories.add(TypeAdapters.BIT_SET_FACTORY);
factories.add(DateTypeAdapter.FACTORY);
factories.add(TypeAdapters.CALENDAR_FACTORY);
factories.add(TimeTypeAdapter.FACTORY);
factories.add(SqlDateTypeAdapter.FACTORY);
factories.add(TypeAdapters.TIMESTAMP_FACTORY);
factories.add(ArrayTypeAdapter.FACTORY);
factories.add(TypeAdapters.ENUM_FACTORY);
factories.add(TypeAdapters.CLASS_FACTORY);
// type adapters for composite and user-defined types
factories.add(new CollectionTypeAdapterFactory(constructorConstructor));
factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization));
factories.add(new ReflectiveTypeAdapterFactory(
constructorConstructor, fieldNamingPolicy, excluder));
this.factories = Collections.unmodifiableList(factories);
}
注册自定义类型适配器
使用方法Gson gson = new GsonBuilder().registerTypeAdapter(Type type, Object typeAdapter),例如注册自定义的日期和Long的类型适配器
Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new DateLongTypeAdapter())
总结:
1. 泛型是理解Gson类型适配器乃至整个Gson的序列化和发序列化的根本,比如ArrayTypeAdapter
2. 什么样的对象会用到ObjectTypeAdapter进行序列化和反序列化