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);
}
這個(gè)方法的實(shí)現(xiàn)亭敢,是調(diào)用了傳入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;
}
這里調(diào)用的fromJson是傳入了一個(gè)Reader對(duì)象
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;
}
這里調(diào)用的fromJson是傳入了JsonReader對(duì)象斟湃,所有的fromJson都會(huì)調(diào)用下面這個(gè)
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實(shí)例封裝成一個(gè)TypeToken實(shí)例
TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);
// 根據(jù)對(duì)應(yīng)的TypeToken苇侵,從typeTokenCache這個(gè)Map緩存中取出對(duì)應(yīng)的TypeAdapter
TypeAdapter<T> typeAdapter = getAdapter(typeToken);
// 調(diào)用對(duì)應(yīng)的TypeAdapter的實(shí)現(xiàn)類的read方法故河,將對(duì)應(yīng)的JsonReader封裝Json字符串之后的對(duì)象解析轉(zhuǎn)換成對(duì)應(yīng)的實(shí)體類
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對(duì)象獲取到了返回的Object對(duì)象爽待,而TypeAdapter是通過getAdapter方法得到的:
@SuppressWarnings("unchecked")
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
// 1.首先嘗試從Gson中的Map緩存中取出對(duì)應(yīng)的TypeAdapter實(shí)現(xiàn)類對(duì)象
TypeAdapter<?> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);
if (cached != null) {
return (TypeAdapter<T>) cached;
}
// 2.
// calls是一個(gè)Gson內(nèi)部的ThreadLocal對(duì)象咧最,是一個(gè)ThreadLocal<Map<TypeToken<?>, FutureTypeAdapter<?>>>類型的,
// 其內(nèi)部存的是一個(gè)Map集合逐纬,而FutureTypeAdapter是TypeAdapter的代理類對(duì)象
// 使用ThreadLocal來緩存FutureTypeAdapter對(duì)象蛔屹,是本地防止getAdapter()的重入調(diào)用
// 其實(shí)就是避免無限遞歸導(dǎo)致一直創(chuàng)建TypeAdapter,最終因?yàn)闊o限遞歸導(dǎo)致棧溢出的問題
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對(duì)應(yīng)的FutureTypeAdapter豁生,則直接返回
// FutureTypeAdapter是一個(gè)委托類兔毒,其實(shí)就是代理類,內(nèi)部保存TypeToken對(duì)應(yīng)的TypeAdapter實(shí)例
// FutureTypeAdapter也是繼承自TypeAdapter
FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type);
if (ongoingCall != null) {
return ongoingCall;
}
try {
//創(chuàng)建FutureTypeAdapter沛硅,保存在ThreadLocal對(duì)象中
FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();
threadCalls.put(type, call);
for (TypeAdapterFactory factory : factories) {
// 在這里可能會(huì)發(fā)生無限遞歸的情況眼刃,即在new Adapter<T>(constructor, getBoundFields(gson, type, raw));
// getBoundFields方法中,會(huì)調(diào)用createBoundField方法封裝每個(gè)Field摇肌,這個(gè)時(shí)候就會(huì)獲取每個(gè)Field的TypeAdapter
// 這里遞歸的主要原因就是create內(nèi)部創(chuàng)建Adapter的時(shí)候,會(huì)調(diào)用getBoundFields方法仪际,其內(nèi)部又會(huì)調(diào)用createBoundField方法围小,
// 在createBoundField方法中又會(huì)調(diào)用Gson.getAdapter昵骤,這樣又遞歸到了Gson.getAdapter,而使用了一個(gè)ThreadLocal肯适,
// 因?yàn)橐呀?jīng)提前put了变秦,遞歸調(diào)用的時(shí)候,第二次同樣的類型執(zhí)行到上面就會(huì)通過return ongoingCall;返回框舔,而不會(huì)執(zhí)行到這里繼續(xù)遞歸
// 使用ThreadLocal的目的就是在遞歸調(diào)用getAdapter的時(shí)候蹦玫,出現(xiàn)TypeToken相同的情況下,在第一次遞歸時(shí)就提前返回刘绣,然后在使用外部類型的TypeAdapter
TypeAdapter<T> candidate = factory.create(this, type);
if (candidate != null) {
// 將通過TypeAdapterFactory.create創(chuàng)建的TypeAdapter委托給對(duì)應(yīng)的FutureTypeAdapter對(duì)象
call.setDelegate(candidate);
// 緩存對(duì)應(yīng)的TypeAdapter
typeTokenCache.put(type, candidate);
return candidate;
}
}
throw new IllegalArgumentException("GSON cannot handle " + type);
} finally {
threadCalls.remove(type);
if (requiresThreadLocalCleanup) {
calls.remove();
}
}
}
上面getAdapter代碼中會(huì)遍歷存儲(chǔ)TypeAdapterFactory的factories樱溉,尋找對(duì)應(yīng)的TypeAdapterFactory實(shí)例,比如返回一個(gè)Bean類的對(duì)象的話纬凤,則會(huì)調(diào)用ReflectiveTypeAdapterFactory福贞,通過這個(gè)Factory.create創(chuàng)建對(duì)應(yīng)的TypeAdapter實(shí)例。
2.屬性說明
private final ThreadLocal<Map<TypeToken<?>, FutureTypeAdapter<?>>> calls
= new ThreadLocal<Map<TypeToken<?>, FutureTypeAdapter<?>>>();
calls是一個(gè)ThreadLocal停士,這個(gè)ThreadLocal緩存了一個(gè)Map集合挖帘,通過對(duì)應(yīng)的TypeToken在當(dāng)前線程中取出對(duì)應(yīng)的FutureTypeAdapter,然后返回恋技。增加一個(gè)ThreadLocal緩存的目的就是為了避免遞歸查找導(dǎo)致無限創(chuàng)建TypeAdapter實(shí)例而出現(xiàn)棧溢出拇舀。
比如:
public class Article {
public Article article;
.....
.....
.....
}
在這個(gè)例子中,一個(gè)Article蜻底,其內(nèi)部有一個(gè)屬性骄崩,也是Article類型的,如果不使用ThreadLocal朱躺,那么就會(huì)出現(xiàn)無限遞歸創(chuàng)建對(duì)應(yīng)的TypeAdapter實(shí)例進(jìn)行解析刁赖。而使用委托類,則會(huì)通過委托類對(duì)象长搀,其內(nèi)部調(diào)用已經(jīng)創(chuàng)建的TypeAdapter進(jìn)行read宇弛。這樣就會(huì)復(fù)用同一個(gè)TypeAdapter實(shí)例。
可以參考下面的文章中的內(nèi)容:
3.ReflectiveTypeAdapterFactory.BoundField相關(guān)
在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);
// 調(diào)用ReflectiveTypeAdapterFactory.getBoundFields方法返回一個(gè)Map集合源请,
// 這個(gè)Map集合的key其實(shí)就是Field的name枪芒,而BoundField其實(shí)就是根據(jù)對(duì)應(yīng)的字段類型、字段名稱等進(jìn)行封裝委托
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();
// 如果真實(shí)類型是Object類型谁尸,則結(jié)束循環(huán)
while (raw != Object.class) {
// 獲取該類型的所有內(nèi)部屬性舅踪,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());
// 獲取字段名稱良蛮,因?yàn)橥ㄟ^Gson注解可以給一個(gè)字段設(shè)置多個(gè)name
List<String> fieldNames = getFieldNames(field);
BoundField previous = null;
for (int i = 0, size = fieldNames.size(); i < size; ++i) {
String name = fieldNames.get(i);
// 只對(duì)默認(rèn)名稱進(jìn)行序列化數(shù)據(jù)
if (i != 0) serialize = false; // only serialize the default name
// 創(chuàng)建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中在根據(jù)name創(chuàng)建BoundField的時(shí)候,已經(jīng)有一個(gè)BoundField
// 這樣的情況說明一個(gè)name有了兩個(gè)BoundField决瞳,則說明一個(gè)類中出現(xiàn)兩個(gè)字段名相同的字段
throw new IllegalArgumentException(declaredType
+ " declares multiple JSON fields named " + previous.name);
}
}
type = TypeToken.get($Gson$Types.resolve(type.getType(), raw, raw.getGenericSuperclass()));
// 獲取父類型货徙,繼續(xù)循環(huán)左权,直到父類型為Object為止。
// 這樣做的目的就是為了Bean類有繼承的情況痴颊,能對(duì)父類屬性進(jìn)行解析赏迟。
raw = type.getRawType();
}
return result;
}
在通過ReflectiveTypeAdapterFactory.create創(chuàng)建TypeAdapter實(shí)例的時(shí)候,通過getBoundFields創(chuàng)建一個(gè)Map集合,主要就是為了對(duì)類的所有屬性進(jìn)行封裝。
// 根據(jù)Field創(chuàng)建BoundField时甚,并且封裝Field的讀寫操作
private ReflectiveTypeAdapterFactory.BoundField createBoundField(
final Gson context, final Field field, final String name,
final TypeToken<?> fieldType, boolean serialize, boolean deserialize) {
// 判斷是否是基本數(shù)據(jù)類型
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其實(shí)就是Gson實(shí)例,這里其實(shí)又是調(diào)用了Gson.getAdapter
if (mapped == null) mapped = context.getAdapter(fieldType);
// 使用final糕再,是便于內(nèi)部類使用
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);
}
// 執(zhí)行Json數(shù)據(jù)的讀取解析操作,然后轉(zhuǎn)換成Object對(duì)象饰豺,通過Field.set亿鲜,給對(duì)應(yīng)的字段設(shè)置value值。
@Override void read(JsonReader reader, Object value)
throws IOException, IllegalAccessException {
// 通過該屬性的類型對(duì)應(yīng)的TypeAdapter嘗試讀取json串
//如果是基礎(chǔ)類型冤吨,則直接讀取蒿柳,
//如果是復(fù)合類型則遞歸之前的流程
// 因?yàn)樵贕son.fromJson方法中,最終就是通過調(diào)用typeAdapter.read進(jìn)行json串解析
// 而這里是又被typeAdapter.read調(diào)用漩蟆,而這里又調(diào)用了typeAdapter.read(reader);
// 其實(shí)就是一個(gè)遞歸調(diào)用流程垒探,即在typeAdapter.read內(nèi)部調(diào)用了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
找到對(duì)應(yīng)的TypeAdapter之后,就會(huì)調(diào)用對(duì)應(yīng)的read方法怠李。以反射方式實(shí)現(xiàn)為例子:
主要是借助了ReflectiveTypeAdapterFactory圾叼,每個(gè)TypeAdapter其實(shí)都是通過對(duì)應(yīng)的Factory的create方法獲取到的。而ReflectiveTypeAdapterFactory中有一個(gè)內(nèi)部類捺癞,就是繼承了TypeAdapter類
public static final class Adapter<T> extends TypeAdapter<T> {
// 用于反射獲取對(duì)象
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中對(duì)應(yīng)的字段名稱是否為空夷蚊,如果為空則跳過
// 這就是為什么json串中有更多字段的數(shù)據(jù),可以使用更少屬性的類來解析髓介,因?yàn)檫@里會(huì)跳過
if (field == null || !field.deserialized) {
in.skipValue();
} else {
// 調(diào)用BoundField.read方法惕鼓,其內(nèi)部會(huì)調(diào)用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需要為什么要使用匿名內(nèi)部類的方式唐础?
new TypeToken<BaseResponse>(){}.getType()箱歧,如果這里不采用創(chuàng)建匿名內(nèi)部類的方式去獲取Type,而是new TypeToken<BaseResponse>().getType()一膨,那么這樣創(chuàng)建的一個(gè)對(duì)象呀邢,在經(jīng)過編譯為.class的時(shí)候,其泛型類型就會(huì)因?yàn)轭愋筒脸兂闪薕bject豹绪,這樣就沒辦法獲取到準(zhǔn)確的Type价淌。
而在這里使用{},其實(shí)就是創(chuàng)建匿名內(nèi)部類對(duì)象,在創(chuàng)建匿名內(nèi)部類對(duì)象输钩,那么其實(shí)就可以認(rèn)為是創(chuàng)建了一個(gè)新的類豺型,就是將舊的TypeToken類的中的泛型T都替換成了BaseResponse的新類仲智。這個(gè)新類买乃,其實(shí)就可以認(rèn)為是TypeToken中的泛型T都為BaseResponse的一個(gè)新類,而不是使用T了钓辆。這樣剪验,在編譯成.class文件的時(shí)候,就不會(huì)因?yàn)榉盒筒脸霈F(xiàn)T變成Object前联,而是編譯成.class之后功戚,其實(shí)就是T都是BaseResponse類型。
匿名內(nèi)部類對(duì)象似嗤,其實(shí)可以認(rèn)為是創(chuàng)建了一個(gè)新的匿名內(nèi)部類啸臀,然后使用這個(gè)匿名內(nèi)部類來創(chuàng)建了一個(gè)對(duì)象。
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這個(gè)類里面的內(nèi)部類來實(shí)現(xiàn)的:
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();
}
}
在內(nèi)部類的Adapter中都會(huì)有一個(gè)read方法,而read方法中伤塌,會(huì)在內(nèi)部調(diào)用elementTypeAdapter這個(gè)類的read方法灯萍,而這個(gè)類的read方法,其實(shí)是調(diào)用的TypeAdapterRuntimeTypeWrapper的read方法每聪,而TypeAdapterRuntimeTypeWrapper的read方法是調(diào)用了ReflectiveTypeAdapterFactory的內(nèi)部類Adapter的read方法旦棉,也就是通過反射拿到一個(gè)個(gè)的對(duì)象。說明List的形式其實(shí)就是通過反射拿到一個(gè)Connection對(duì)象药薯,再通過反射拿到一個(gè)個(gè)的對(duì)象绑洛,然后將這些對(duì)象放到Connection中。Map的方式其實(shí)是類似的童本。
(3)返回Map集合
返回Map集合中真屯,Gson.java類中的getAdapter方法中的TypeAdapter<T> candidate = factory.create(this, type);最終是調(diào)用的MapTypeAdapterFactory類的create方法。而在這里巾陕,會(huì)分別創(chuàng)建兩個(gè)TypeAdapter讨跟,也就是KeyAdapter和ValueAdapter,這兩個(gè)Adapter都是ObjectTypeAdapter的實(shí)例對(duì)象鄙煤。
如果key是一個(gè)String晾匠、int、boolean這樣的類型的梯刚,則KeyTypeAdapter對(duì)象其實(shí)就是從TypeAdapters中的對(duì)應(yīng)的TypeAdapter的實(shí)現(xiàn)類凉馆。而value如果是Object,那么則是通過ReflectiveTypeAdapterFactory的靜態(tài)final內(nèi)部類Adapter返回對(duì)應(yīng)的Object的,其實(shí)就是通過反射的方式返回的澜共。
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是個(gè)很重要的變量向叉,默認(rèn)值為PEEKED_NONE。在上面的方法中嗦董,調(diào)用了一個(gè)方法doPeek()母谎,這個(gè)類可以說是JsonReader類的核心方法之一。