携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情
Gson源码解析(一)Gson序列化流程
我们从fromJson开始。
public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
Object object = fromJson(json, (Type) classOfT);
return Primitives.wrap(classOfT).cast(object);
}
经过几个fromJson重载方法后,会将我们传入的json一步步封装 String -> StringReader -> JsonReader;将传入的类类型Class变为Type。
Note:JsonReader是流式JSON解析器。它读取文字值(字符串,数字,布尔值和空值)以及对象和数组的开始和结束分隔符,并将他们以令牌流的形式推送。
public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
boolean isEmpty = true;
boolean oldLenient = reader.isLenient();
reader.setLenient(true);
try {
reader.peek();
isEmpty = false;
TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);
TypeAdapter<T> typeAdapter = getAdapter(typeToken);
T object = typeAdapter.read(reader);
return object;
...
//省略非关键代码
}
Note:这里的TypeToken是用来在运行时获取泛型参数的具体类型的工具类。
可以看到最终是通过TypeAdapter.read方法来解析json。TypeAdapter从何而来?我们进入getAdapter(TypeToken<T> type)方法看看。
getAdapter
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
//1.尝试从typeTokenCache缓存里获取TypeAdapter
TypeAdapter<?> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);
if (cached != null) {
return (TypeAdapter<T>) cached;
}
Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();
boolean requiresThreadLocalCleanup = false;
if (threadCalls == null) {
threadCalls = new HashMap<TypeToken<?>, FutureTypeAdapter<?>>();
calls.set(threadCalls);
requiresThreadLocalCleanup = true;
}
//2.尝试从threadCalls缓存中获取TypeAdapter
FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type);
if (ongoingCall != null) {
return ongoingCall;
}
//3.两个缓存中都没有的话就创建一个
try {
FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();
threadCalls.put(type, call);
for (TypeAdapterFactory factory : factories) {
TypeAdapter<T> candidate = factory.create(this, type);
if (candidate != null) {
//存入缓存中(threadCalls和typeTokenCache)
call.setDelegate(candidate);
typeTokenCache.put(type, candidate);
return candidate;
}
}
throw new IllegalArgumentException("GSON (" + GsonBuildConfig.VERSION + ") cannot handle " + type);
} finally {
threadCalls.remove(type);
if (requiresThreadLocalCleanup) {
calls.remove();
}
}
}
1.getAdapter方法首先从Gson的成员变量Map<TypeToken<?>, TypeAdapter<?>> typeTokenCache 中查找TypeAdapter;
2.然后在从threadCalls缓存中查找TypeAdapter,threadCalls使用了ThreadLocal存储缓存。
calls = new ThreadLocal<Map<TypeToken<?>, FutureTypeAdapter<?>>>();
threadlocal是一个线程内部的存储类,可以在指定线程内存储数据,数据存储以后,只有指定线程可以得到存储数据。
3.缓存中都没有的话就根据type创建一个TypeAdapter。
这里使用了两个缓存,一个存储在Gson实例的局部变量里,一个存储在线程的局部变量里。这样不管是使用同一个Gson实例解析json,还是在同一线程下使用不同Gson实例解析json都可以高效的获得TypeAdapter。
接下来我们来看看factories是怎样创建TypeAdapter的。
factories是在Gson的构造器里初始化的。
Gson(...) {
...
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);
// users' type adapters
factories.addAll(factoriesToBeAdded);
// 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);
TypeAdapter<Number> longAdapter = longAdapter(longSerializationPolicy);
factories.add(TypeAdapters.newFactory(long.class, Long.class, longAdapter));
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.ATOMIC_INTEGER_FACTORY);
factories.add(TypeAdapters.ATOMIC_BOOLEAN_FACTORY);
factories.add(TypeAdapters.newFactory(AtomicLong.class, atomicLongAdapter(longAdapter)));
factories.add(TypeAdapters.newFactory(AtomicLongArray.class, atomicLongArrayAdapter(longAdapter)));
factories.add(TypeAdapters.ATOMIC_INTEGER_ARRAY_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.CURRENCY_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.CLASS_FACTORY);
// type adapters for composite and user-defined types
factories.add(new CollectionTypeAdapterFactory(constructorConstructor));
factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization));
this.jsonAdapterFactory = new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor);
factories.add(jsonAdapterFactory);
factories.add(TypeAdapters.ENUM_FACTORY);
factories.add(new ReflectiveTypeAdapterFactory(
constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory));
this.factories = Collections.unmodifiableList(factories);
}
可以看到factories是一个ArrayList,其存储类型是TypeAdapterFactory,并在初始化的时候添加了各种类型的TypeAdapterFactory。
public interface TypeAdapterFactory {
<T> TypeAdapter<T> create(Gson gson, TypeToken<T> type);
}
Gson中其实充斥了大量的TypeAdapterFactory,包基本类型的、用户自定义的等等。
我们先看下基本类型的TypeAdapters.STRING_FACTORY。
public static final TypeAdapterFactory STRING_FACTORY = newFactory(String.class, STRING);
public static <TT> TypeAdapterFactory newFactory(
final Class<TT> type, final TypeAdapter<TT> typeAdapter) {
return new TypeAdapterFactory() {
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
return typeToken.getRawType() == type ? (TypeAdapter<T>) typeAdapter : null;
}
...
//省略非关键代码
};
}
public static final TypeAdapter<String> STRING = new TypeAdapter<String>() {
@Override
public String read(JsonReader in) throws IOException {
JsonToken peek = in.peek();
if (peek == JsonToken.NULL) {
in.nextNull();
return null;
}
/* coerce booleans to strings for backwards compatibility */
if (peek == JsonToken.BOOLEAN) {
return Boolean.toString(in.nextBoolean());
}
return in.nextString();
}
@Override
public void write(JsonWriter out, String value) throws IOException {
out.value(value);
}
};
总结
如果解析一个String类型的数据,大概的逻辑会是这样的:
- Gson初始化时通过newFactory方法将String类型的TypeAdapter包装成TypeAdapterFactory。
- 开始解析时会在上文的提到的
getAdaapter()中获取该TypeAdapterFactory。 - 再调用create方法得到String类型的TypeAdapter。
- 最后调用TypeAdapter的read方法将json转化为String。
好像有哪里不对劲...
为什么不直接去查找TypeAdapter了?为什么中间要加个TypeAdapterFactory了?这不是脱裤子放屁吗?好问题,我现在也不知道,有没有同学教一下。
看到这里我们终于看到了read方法了,TypeAdapter的read方法作用就是将Json转化为Java Object;write方法时将Java Object转化为Json。但是我们使用Gson时传入的是JavaBean,不是基本类型,这时该怎么获取TypeAdapter去解析json了?欲知后事如何,请看下回分解。
TypeToken
TypeToken是用来获取泛型的参数类型的。
data class User(val id: Long, val name: String)
...
//返回List<User>类型
val type = object :TypeToken<List<User>>(){}.type
//返回List类型
val rawType = object :TypeToken<List<User>>(){}.rawType
疑惑
大家都知道java的泛型擦除机制的存在,那么为什么Gson可以在运行时拿到具体的泛型类型了?
List<String> l1 = new ArrayList<String>();
List<Integer> l2 = new ArrayList<Integer>();
System.out.println(l1.getClass() == l2.getClass());
回想刚开始学java时看到的博客 “为了兼容jdk1.5之前的版本,java会在编译期擦除与泛型相关的信息。”
这句话是对的,但没有完全对,有被误导到...
techblog.bozho.net/on-java-gen… zhuanlan.zhihu.com/p/292983882…
参考了上面两篇博客了解到编译期并不会完全擦除泛型信息:
- 1、泛型不止在编译阶段生效,部分泛型可以在运行时通过反射获取;
- 2、java 语言尝试将所有能确定的泛型信息记录在类文件中。
未被擦除的泛型
父类泛型、成员变量、方法入参和返回值使用到的泛型信息都会保留,并能在运行阶段获取。
public static void main(String[] args) throws Exception {
// 获取父类泛型
System.out.println("GenericSuperclass:" + ((ParameterizedType) (Clazz.class.getGenericSuperclass())).getActualTypeArguments()[0]);
// 获取成员变量泛型
Field field = Clazz.class.getDeclaredField("field");
for (Type fieldType : ((ParameterizedType) (field.getGenericType())).getActualTypeArguments()) {
System.out.println("field:" + fieldType.getTypeName());
}
// 获取方法入参和返回值泛型
Method method = Clazz.class.getDeclaredMethod("function", List.class);
for (Type type : method.getGenericParameterTypes()) {
System.out.println("method param:" + ((ParameterizedType) type).getActualTypeArguments()[0]);
}
System.out.println("method return:" + ((ParameterizedType) method.getGenericReturnType()).getActualTypeArguments()[0]);
}
参数化类型 ParameterizedType
public interface ParameterizedType extends Type {
//返回确切的泛型参数, 如Map<String, Integer>返回[String, Integer]
Type[] getActualTypeArguments();
//返回当前class或interface声明的类型, 如List<?>返回List
Type getRawType();
//返回所属类型. 这主要是对嵌套定义的内部类而言的,例如于对Map.Entry<K,V>来说,调用getOwnerType方法返回的就是Map。
Type getOwnerType();
}
TypeToken的实现
再回过头看一看TypeToken的实现就简单了。
public class TypeToken<T> {
final Class<? super T> rawType;
final Type type;
final int hashCode;
@SuppressWarnings("unchecked")
protected TypeToken() {
this.type = getSuperclassTypeParameter(getClass());
this.rawType = (Class<? super T>) $Gson$Types.getRawType(type);
this.hashCode = type.hashCode();
}
...
}
val type = object :TypeToken<List<User>>(){}.type
通过匿名类的形式创建实例,此时实例的父类型就是TypeToken<List<User>>。
这个类的无参构造函数是protected,所以只能使用继承的方式去创建一个实例。构造函数第一行调用了getSuperclassTypeParameter,我们定位到此方法。
static Type getSuperclassTypeParameter(Class<?> subclass) {
Type superclass = subclass.getGenericSuperclass();
//如果返回的是Class类型则抛出错误
if (superclass instanceof Class) {
throw new RuntimeException("Missing type parameter.");
}
ParameterizedType parameterized = (ParameterizedType) superclass;
return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
}
调用getGenericSuperclass()便可以得到TypeToken<List<User>>的参数化类型,从而得到List<User>类型信息。