1.fromJson
public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
Object object = fromJson(json, (Type) classOfT);
return Primitives.wrap(classOfT).cast(object);
}
这个方法的实现,是调用了传入Type的fromJson
public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
if (json == null) {
return null;
}
StringReader reader = new StringReader(json);
T target = (T) fromJson(reader, typeOfT);
return target;
}
这里调用的fromJson是传入了一个Reader对象
public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
JsonReader jsonReader = newJsonReader(json);
T object = (T) fromJson(jsonReader, typeOfT);
assertFullConsumption(object, jsonReader);
return object;
}
这里调用的fromJson是传入了JsonReader对象,所有的fromJson都会调用下面这个
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;
// 将传入的Type实例封装成一个TypeToken实例
TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);
// 根据对应的TypeToken,从typeTokenCache这个Map缓存中取出对应的TypeAdapter
TypeAdapter<T> typeAdapter = getAdapter(typeToken);
// 调用对应的TypeAdapter的实现类的read方法,将对应的JsonReader封装Json字符串之后的对象解析转换成对应的实体类
T object = typeAdapter.read(reader);
return object;
} catch (EOFException e) {
/*
* For compatibility with JSON 1.5 and earlier, we return null for empty
* documents instead of throwing.
*/
if (isEmpty) {
return null;
}
throw new JsonSyntaxException(e);
} catch (IllegalStateException e) {
throw new JsonSyntaxException(e);
} catch (IOException e) {
// TODO(inder): Figure out whether it is indeed right to rethrow this as JsonSyntaxException
throw new JsonSyntaxException(e);
} finally {
reader.setLenient(oldLenient);
}
}
在这里,是通过TypeAdapter对象获取到了返回的Object对象,而TypeAdapter是通过getAdapter方法得到的:
@SuppressWarnings("unchecked")
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
// 1.首先尝试从Gson中的Map缓存中取出对应的TypeAdapter实现类对象
TypeAdapter<?> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);
if (cached != null) {
return (TypeAdapter<T>) cached;
}
// 2.
// calls是一个Gson内部的ThreadLocal对象,是一个ThreadLocal<Map<TypeToken<?>, FutureTypeAdapter<?>>>类型的,
// 其内部存的是一个Map集合,而FutureTypeAdapter是TypeAdapter的代理类对象
// 使用ThreadLocal来缓存FutureTypeAdapter对象,是本地防止getAdapter()的重入调用
// 其实就是避免无限递归导致一直创建TypeAdapter,最终因为无限递归导致栈溢出的问题
Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();
boolean requiresThreadLocalCleanup = false;
if (threadCalls == null) {
threadCalls = new HashMap<TypeToken<?>, FutureTypeAdapter<?>>();
calls.set(threadCalls);
requiresThreadLocalCleanup = true;
}
// 3.如果在ThreadLocal中的Map中找到了TypeToken对应的FutureTypeAdapter,则直接返回
// FutureTypeAdapter是一个委托类,其实就是代理类,内部保存TypeToken对应的TypeAdapter实例
// FutureTypeAdapter也是继承自TypeAdapter
FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type);
if (ongoingCall != null) {
return ongoingCall;
}
try {
//创建FutureTypeAdapter,保存在ThreadLocal对象中
FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();
threadCalls.put(type, call);
for (TypeAdapterFactory factory : factories) {
// 在这里可能会发生无限递归的情况,即在new Adapter<T>(constructor, getBoundFields(gson, type, raw));
// getBoundFields方法中,会调用createBoundField方法封装每个Field,这个时候就会获取每个Field的TypeAdapter
// 这里递归的主要原因就是create内部创建Adapter的时候,会调用getBoundFields方法,其内部又会调用createBoundField方法,
// 在createBoundField方法中又会调用Gson.getAdapter,这样又递归到了Gson.getAdapter,而使用了一个ThreadLocal,
// 因为已经提前put了,递归调用的时候,第二次同样的类型执行到上面就会通过return ongoingCall;返回,而不会执行到这里继续递归
// 使用ThreadLocal的目的就是在递归调用getAdapter的时候,出现TypeToken相同的情况下,在第一次递归时就提前返回,然后在使用外部类型的TypeAdapter
TypeAdapter<T> candidate = factory.create(this, type);
if (candidate != null) {
// 将通过TypeAdapterFactory.create创建的TypeAdapter委托给对应的FutureTypeAdapter对象
call.setDelegate(candidate);
// 缓存对应的TypeAdapter
typeTokenCache.put(type, candidate);
return candidate;
}
}
throw new IllegalArgumentException("GSON cannot handle " + type);
} finally {
threadCalls.remove(type);
if (requiresThreadLocalCleanup) {
calls.remove();
}
}
}
上面getAdapter代码中会遍历存储TypeAdapterFactory的factories,寻找对应的TypeAdapterFactory实例,比如返回一个Bean类的对象的话,则会调用ReflectiveTypeAdapterFactory,通过这个Factory.create创建对应的TypeAdapter实例。
2.属性说明
private final ThreadLocal<Map<TypeToken<?>, FutureTypeAdapter<?>>> calls
= new ThreadLocal<Map<TypeToken<?>, FutureTypeAdapter<?>>>();
calls是一个ThreadLocal,这个ThreadLocal缓存了一个Map集合,通过对应的TypeToken在当前线程中取出对应的FutureTypeAdapter,然后返回。增加一个ThreadLocal缓存的目的就是为了避免递归查找导致无限创建TypeAdapter实例而出现栈溢出。
比如:
public class Article {
public Article article;
.....
.....
.....
}
在这个例子中,一个Article,其内部有一个属性,也是Article类型的,如果不使用ThreadLocal,那么就会出现无限递归创建对应的TypeAdapter实例进行解析。而使用委托类,则会通过委托类对象,其内部调用已经创建的TypeAdapter进行read。这样就会复用同一个TypeAdapter实例。
可以参考下面的文章中的内容:
3.ReflectiveTypeAdapterFactory.BoundField相关
在ReflectiveTypeAdapterFactory.create方法如下:
@Override public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
Class<? super T> raw = type.getRawType();
if (!Object.class.isAssignableFrom(raw)) {
return null; // it's a primitive!
}
ObjectConstructor<T> constructor = constructorConstructor.get(type);
// 调用ReflectiveTypeAdapterFactory.getBoundFields方法返回一个Map集合,
// 这个Map集合的key其实就是Field的name,而BoundField其实就是根据对应的字段类型、字段名称等进行封装委托
return new Adapter<T>(constructor, getBoundFields(gson, type, raw));
}
private Map<String, BoundField> getBoundFields(Gson context, TypeToken<?> type, Class<?> raw) {
Map<String, BoundField> result = new LinkedHashMap<String, BoundField>();
if (raw.isInterface()) {
return result;
}
Type declaredType = type.getType();
// 如果真实类型是Object类型,则结束循环
while (raw != Object.class) {
// 获取该类型的所有内部属性,getDeclaredFields()方法是获取本类型,不包括父类的所有属性(包括私有属性)
Field[] fields = raw.getDeclaredFields();
// 遍历所有字段
for (Field field : fields) {
boolean serialize = excludeField(field, true);
boolean deserialize = excludeField(field, false);
if (!serialize && !deserialize) {
continue;
}
field.setAccessible(true);
// 获取字段的类型
Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType());
// 获取字段名称,因为通过Gson注解可以给一个字段设置多个name
List<String> fieldNames = getFieldNames(field);
BoundField previous = null;
for (int i = 0, size = fieldNames.size(); i < size; ++i) {
String name = fieldNames.get(i);
// 只对默认名称进行序列化数据
if (i != 0) serialize = false; // only serialize the default name
// 创建BoundField
BoundField boundField = createBoundField(context, field, name,
TypeToken.get(fieldType), serialize, deserialize);
// 替换Map中已有的value
BoundField replaced = result.put(name, boundField);
if (previous == null) previous = replaced;
}
if (previous != null) {
// 如果previous不为null,说明Map中在根据name创建BoundField的时候,已经有一个BoundField
// 这样的情况说明一个name有了两个BoundField,则说明一个类中出现两个字段名相同的字段
throw new IllegalArgumentException(declaredType
+ " declares multiple JSON fields named " + previous.name);
}
}
type = TypeToken.get($Gson$Types.resolve(type.getType(), raw, raw.getGenericSuperclass()));
// 获取父类型,继续循环,直到父类型为Object为止。
// 这样做的目的就是为了Bean类有继承的情况,能对父类属性进行解析。
raw = type.getRawType();
}
return result;
}
在通过ReflectiveTypeAdapterFactory.create创建TypeAdapter实例的时候,通过getBoundFields创建一个Map集合,主要就是为了对类的所有属性进行封装。
// 根据Field创建BoundField,并且封装Field的读写操作
private ReflectiveTypeAdapterFactory.BoundField createBoundField(
final Gson context, final Field field, final String name,
final TypeToken<?> fieldType, boolean serialize, boolean deserialize) {
// 判断是否是基本数据类型
final boolean isPrimitive = Primitives.isPrimitive(fieldType.getRawType());
// special casing primitives here saves ~5% on Android...
JsonAdapter annotation = field.getAnnotation(JsonAdapter.class);
TypeAdapter<?> mapped = null;
if (annotation != null) {
mapped = jsonAdapterFactory.getTypeAdapter(
constructorConstructor, context, fieldType, annotation);
}
final boolean jsonAdapterPresent = mapped != null;
// Gson尝试获取该Field字段类型的TypeAdapter
// 这里的context其实就是Gson实例,这里其实又是调用了Gson.getAdapter
if (mapped == null) mapped = context.getAdapter(fieldType);
// 使用final,是便于内部类使用
final TypeAdapter<?> typeAdapter = mapped;
return new ReflectiveTypeAdapterFactory.BoundField(name, serialize, deserialize) {
@SuppressWarnings({"unchecked", "rawtypes"}) // the type adapter and field type always agree
@Override void write(JsonWriter writer, Object value)
throws IOException, IllegalAccessException {
Object fieldValue = field.get(value);
TypeAdapter t = jsonAdapterPresent ? typeAdapter
: new TypeAdapterRuntimeTypeWrapper(context, typeAdapter, fieldType.getType());
t.write(writer, fieldValue);
}
// 执行Json数据的读取解析操作,然后转换成Object对象,通过Field.set,给对应的字段设置value值。
@Override void read(JsonReader reader, Object value)
throws IOException, IllegalAccessException {
// 通过该属性的类型对应的TypeAdapter尝试读取json串
//如果是基础类型,则直接读取,
//如果是复合类型则递归之前的流程
// 因为在Gson.fromJson方法中,最终就是通过调用typeAdapter.read进行json串解析
// 而这里是又被typeAdapter.read调用,而这里又调用了typeAdapter.read(reader);
// 其实就是一个递归调用流程,即在typeAdapter.read内部调用了typeAdapter.read(reader);
Object fieldValue = typeAdapter.read(reader);
if (fieldValue != null || !isPrimitive) {
field.set(value, fieldValue);
}
}
@Override public boolean writeField(Object value) throws IOException, IllegalAccessException {
if (!serialized) return false;
Object fieldValue = field.get(value);
return fieldValue != value; // avoid recursion for example for Throwable.cause
}
};
}
4.ReflectiveTypeAdapterFactory.read
找到对应的TypeAdapter之后,就会调用对应的read方法。以反射方式实现为例子:
主要是借助了ReflectiveTypeAdapterFactory,每个TypeAdapter其实都是通过对应的Factory的create方法获取到的。而ReflectiveTypeAdapterFactory中有一个内部类,就是继承了TypeAdapter类
public static final class Adapter<T> extends TypeAdapter<T> {
// 用于反射获取对象
private final ObjectConstructor<T> constructor;
private final Map<String, BoundField> boundFields;
Adapter(ObjectConstructor<T> constructor, Map<String, BoundField> boundFields) {
this.constructor = constructor;
this.boundFields = boundFields;
}
@Override public T read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
T instance = constructor.construct();
try {
in.beginObject();
while (in.hasNext()) {
String name = in.nextName();
BoundField field = boundFields.get(name);
// 判断boundFields中对应的字段名称是否为空,如果为空则跳过
// 这就是为什么json串中有更多字段的数据,可以使用更少属性的类来解析,因为这里会跳过
if (field == null || !field.deserialized) {
in.skipValue();
} else {
// 调用BoundField.read方法,其内部会调用TypeAdapter.read
field.read(in, instance);
}
}
} catch (IllegalStateException e) {
throw new JsonSyntaxException(e);
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
in.endObject();
return instance;
}
@Override public void write(JsonWriter out, T value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
out.beginObject();
try {
for (BoundField boundField : boundFields.values()) {
if (boundField.writeField(value)) {
out.name(boundField.name);
boundField.write(out, value);
}
}
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
out.endObject();
}
}
Gson解析中,使用ReflectiveTypeAdapterFactory的解析过程:
5.使用TypeToken需要为什么要使用匿名内部类的方式?
new TypeToken<BaseResponse>(){}.getType(),如果这里不采用创建匿名内部类的方式去获取Type,而是new TypeToken<BaseResponse>().getType(),那么这样创建的一个对象,在经过编译为.class的时候,其泛型类型就会因为类型擦除而变成了Object,这样就没办法获取到准确的Type。
而在这里使用{},其实就是创建匿名内部类对象,在创建匿名内部类对象,那么其实就可以认为是创建了一个新的类,就是将旧的TypeToken类的中的泛型T都替换成了BaseResponse的新类。这个新类,其实就可以认为是TypeToken中的泛型T都为BaseResponse的一个新类,而不是使用T了。这样,在编译成.class文件的时候,就不会因为泛型擦除而出现T变成Object,而是编译成.class之后,其实就是T都是BaseResponse类型。
匿名内部类对象,其实可以认为是创建了一个新的匿名内部类,然后使用这个匿名内部类来创建了一个对象。
6.Excluder排序器
主要是为了处理一些不需要序列化和不需要反序列化的一些字段的。
(2)返回list集合的fromJson
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
// type的值是java.util.list<类路径>
TypeAdapter<?> cached = typeTokenCache.get(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;
}
// the key and value type parameters always agree
FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type);
if (ongoingCall != null) {
return ongoingCall;
}
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) {
call.setDelegate(candidate);
typeTokenCache.put(type, candidate);
return candidate;
}
}
throw new IllegalArgumentException("GSON cannot handle " + type);
} finally {
threadCalls.remove(type);
if (requiresThreadLocalCleanup) {
calls.remove();
}
}
}
而返回List集合,是通过CollectionTypeAdapterFactory这个类里面的内部类来实现的:
private static final class Adapter<E> extends TypeAdapter<Collection<E>> {
private final TypeAdapter<E> elementTypeAdapter;
private final ObjectConstructor<? extends Collection<E>> constructor;
public Adapter(Gson context, Type elementType,
TypeAdapter<E> elementTypeAdapter,
ObjectConstructor<? extends Collection<E>> constructor) {
this.elementTypeAdapter = new TypeAdapterRuntimeTypeWrapper<E>(context, elementTypeAdapter, elementType);
this.constructor = constructor;
}
@Override public Collection<E> read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
Collection<E> collection = constructor.construct();
in.beginArray();
while (in.hasNext()) {
E instance = elementTypeAdapter.read(in);
collection.add(instance);
}
in.endArray();
return collection;
}
@Override public void write(JsonWriter out, Collection<E> collection) throws IOException {
if (collection == null) {
out.nullValue();
return;
}
out.beginArray();
for (E element : collection) {
elementTypeAdapter.write(out, element);
}
out.endArray();
}
}
在内部类的Adapter中都会有一个read方法,而read方法中,会在内部调用elementTypeAdapter这个类的read方法,而这个类的read方法,其实是调用的TypeAdapterRuntimeTypeWrapper的read方法,而TypeAdapterRuntimeTypeWrapper的read方法是调用了ReflectiveTypeAdapterFactory的内部类Adapter的read方法,也就是通过反射拿到一个个的对象。说明List的形式其实就是通过反射拿到一个Connection对象,再通过反射拿到一个个的对象,然后将这些对象放到Connection中。Map的方式其实是类似的。
(3)返回Map集合
返回Map集合中,Gson.java类中的getAdapter方法中的TypeAdapter<T> candidate = factory.create(this, type);最终是调用的MapTypeAdapterFactory类的create方法。而在这里,会分别创建两个TypeAdapter,也就是KeyAdapter和ValueAdapter,这两个Adapter都是ObjectTypeAdapter的实例对象。
如果key是一个String、int、boolean这样的类型的,则KeyTypeAdapter对象其实就是从TypeAdapters中的对应的TypeAdapter的实现类。而value如果是Object,那么则是通过ReflectiveTypeAdapterFactory的静态final内部类Adapter返回对应的Object的,其实就是通过反射的方式返回的。
JsonReader解析:
(1)beginObject()
int peeked = PEEKED_NONE;
public void beginObject() throws IOException {
int p = peeked;
if (p == PEEKED_NONE) {
p = doPeek();
}
if (p == PEEKED_BEGIN_OBJECT) {
push(JsonScope.EMPTY_OBJECT);
peeked = PEEKED_NONE;
} else {
throw new IllegalStateException("Expected BEGIN_OBJECT but was " + peek() + locationString());
}
}
peeked是个很重要的变量,默认值为PEEKED_NONE。在上面的方法中,调用了一个方法doPeek(),这个类可以说是JsonReader类的核心方法之一。