上面我們學習了gson 的序列化過程方法 toJson 的源碼,相信對很多的流程有了一個瞭解,緊接着我們來學習下gson反序列化過程,fromJson .還是老樣子,代碼一點一點看。
我們先模擬一個反序列化過程
String json="{\"age\":30,\"name\":\"明\",\"len\":170]}";
TestMode jsTestMode=gson.fromJson(json,TestMode.class);
public class TestMode {
@Expose(deserialize = true)
private int age;
@Expose(serialize = false, deserialize = true)
String name;
@Expose(deserialize = true)
@SerializedName("len")
int length;
// public List<TestMode> getTestMode() {
// return testMode;
// }
//
// public void setTestMode(List<TestMode> testMode) {
// this.testMode = testMode;
// }
//
// List<TestMode> testMode;
public TestMode(){
}
public TestMode(int age, String name, int length) {
this.age = age;
this.name = name;
this.length = length;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "TestMode{" +
"age=" + age +
", name='" + name + '\'' +
", length=" + length +
// ", testMode=" + testMode +
'}';
}
}
//classofT 就 是我們要將json 字符串反序列位的對象的.class 類
public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
//生成一個object對象 ,class 轉爲type接口類型,因爲class<T> 本身實現了type接口
Object object = fromJson(json, (Type) classOfT);
//將object 轉爲 具體的類對象並返回
return Primitives.wrap(classOfT).cast(object);
}
//
public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
if (json == null) {
return null;
}
// 將json 字符串封裝到StringReader 類中 StringReader繼承自Reader 類 用來處理流相關字符串。
StringReader reader = new StringReader(json);
T target = (T) fromJson(reader, typeOfT);
return target;
}
public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
對字符串流做一個封裝,放入jsonReader中,同時,jsonReader 也是反序列的關鍵類,基本所有的字符到對象的具體的操作邏輯都是由它來實現的
JsonReader jsonReader = newJsonReader(json);
T object = (T) fromJson(jsonReader, typeOfT);
//在整個反序列化過程結束之前效驗 jsonReader 的 peeked 的狀態
//如果 peeker 未處於結束狀態,則會報錯
assertFullConsumption(object, jsonReader);
return object;
}
前面是一些準備的fromJson 構造函數,下面看主要部分
public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
boolean isEmpty = true;
// 接受不符合規定的json變量的值
boolean oldLenient = reader.isLenient();
//強制設置爲接受
reader.setLenient(true);
try {
//此處相當於調用了一次 JsonReader 中的 doPeek() 方法,返回下一個令牌的類型而不消耗它,設置當前令牌
reader.peek();
isEmpty = false;
//TypeToken 本質上是 Class 的增強封裝類
TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);
//根據要轉化的實體類型,獲取相應的適配器
TypeAdapter<T> typeAdapter = getAdapter(typeToken);
//通過適配器生成實體類
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);
} catch (AssertionError e) {
AssertionError error = new AssertionError("AssertionError (GSON " + GsonBuildConfig.VERSION + "): " + e.getMessage());
error.initCause(e);
throw error;
} finally {
reader.setLenient(oldLenient);
}
}
主要看下 getAdapter 方法
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
//TypeToken<T> 類字面翻譯是類型令牌,其實就是保存了這個類的屬性,類型和hashcode等值爲後期操作準備
//typeTokenCache 內部是一個線程安全的ConcurrentHashMap ,它主要用來緩存類型令牌,如果能夠獲取到值,那說明之前已經有了相同的類型令牌,也就是說是同一個,如果有了就直接返回
TypeAdapter<?> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);
if (cached != null) {
return (TypeAdapter<T>) cached;
}
//calls 是一個 ThreadLocal 對象 ,當前線程中保存一份緩存,裏面存入的對象會在 finally 代碼塊中清空掉
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);
//factories 是適配器集合工廠,通過遍歷找到相關類型
for (TypeAdapterFactory factory : factories) {
//根據上邊我們的實體類 type可以判斷最終執行 ReflectiveTypeAdapterFactory 的create方法返回值不爲空,所以他的適配器類型是這樣確定的 ,如果不算自定義是41種適配器,當然,方法對於不是對應類型的參數會返回 null,所以不爲空說明找到了對應的適配器類型。
//完整的適配器包括它類本身的適配器類型,還包括它所有變量的適配器類型,call存儲的就是這樣的數據,因爲create 執行後,會通過反射獲取到所有類中變量名稱,並且通過getAdapter 也就是當前方法獲取類型,這是如果之前已經有這個適配器存儲了,就直接返回了ongoingCall
TypeAdapter<T> candidate = factory.create(this, type);
if (candidate != null) {
// 將對應的適配器類型緩存起來
call.setDelegate(candidate);
typeTokenCache.put(type, candidate);
return candidate;
}
}
throw new IllegalArgumentException("GSON (" + GsonBuildConfig.VERSION + ") cannot handle " + type);
} finally {
//清除 ThreadLocal 緩存
threadCalls.remove(type);
if (requiresThreadLocalCleanup) {
calls.remove();
}
}
}
這裏返回了該類對應的適配器類型。並且對應變量也會調用到這個方法來獲取變量的適配器類型。
typeAdapter.read(reader); 是適配器中的read 方法,不同的類對應的適配器是不同的
所有的適配器類都實現了TypeAdapterFactory 適配器工廠接口, 重寫了create 方法,而create 的返回值是一個adapter類,所有的adapter 都繼承 TypeAdapter<T> 並且實現了其中的抽象方法read 和write。我們的TestMode 對應的是 ReflectiveTypeAdapterFactory
factories.add(TypeAdapters.INET_ADDRESS_FACTORY); 這個是基本類型等的適配器 是TypeAdapters ,例如bool string 等
直接看ReflectiveTypeAdapterFactory的create
@Override public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
Class<? super T> raw = type.getRawType();
//這裏用於比對類型,如果不是相應的類型就返回null
//確定此* {@code Class}對象表示的類或接口是否與指定的{{code code}}參數所表示的類或接口相同,或者是該類或接口的超類或父接口。 。如果是,則返回{@code true}; *否則返回{@code false}
//很顯然,這裏返回的是true 應爲我們的類是TestMode 是一個class類
if (!Object.class.isAssignableFrom(raw)) {
return null; // it's a primitive!
}
//通用對象構造工廠
ObjectConstructor<T> constructor = constructorConstructor.get(type);
return new Adapter<T>(constructor, getBoundFields(gson, type, raw));
}
然後看下adapter 構造方法
getBoundFields 方法就是通過反射獲取所有變量屬性
Map<String, BoundField> result = new LinkedHashMap<String, BoundField>();
key 對應的是字段名,BoundField 是對該字段的屬性的保存。
static abstract class BoundField {
final String name;
final boolean serialized;
final boolean deserialized;
protected BoundField(String name, boolean serialized, boolean deserialized) {
this.name = name;
this.serialized = serialized;
this.deserialized = deserialized;
}
abstract boolean writeField(Object value) throws IOException, IllegalAccessException;
abstract void write(JsonWriter writer, Object value) throws IOException, IllegalAccessException;
abstract void read(JsonReader reader, Object value) throws IOException, IllegalAccessException;
}
現在回到typeAdapter.read 方法 while 循環執行,直到反序列化結束。
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;
}
//創建一個實例化對象 就是 TestMode
T instance = constructor.construct();
try {
//開始反序列化前的準備
in.beginObject();
//是否還有下一個,沒有返回false 有返回true 並設置指令
while (in.hasNext()) {
//獲取json 中的一個key
String name = in.nextName();
//通過key 找到對應的屬性對象
BoundField field = boundFields.get(name);
if (field == null || !field.deserialized) {
in.skipValue();
} else {
//開始讀入
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 {...}
}
我們之前做的所有的準備工作都會在這個類中提現出來。字符傳中提取key 並獲取到field ,然後執行field 的read 方法,BoundField 重寫read 方法
@Override void read(JsonReader reader, Object value)
throws IOException, IllegalAccessException {
//根據json字符串和適配器,讀取當前field 的value 值
Object fieldValue = typeAdapter.read(reader);
if (fieldValue != null || !isPrimitive) {
//根據field (key 對應的field)設置值到value (TestDoem) 中 fieldValue (對象值)
field.set(value, fieldValue);
}
}
到這裏整個流程就結束了,下面我們來看前面的幾個具體操作類
doPeek()
//JsonReader.class
int doPeek() throws IOException {
//stack 是一個定義在 JsonReader 中的 int 數組,作爲 JsonReader 的指令集存在,用於控制變量 peeked 的狀態
//在 JsonReader 初始化的時候會將 stack 的第一個元素變成6,其餘均爲0
//6的意思根據官方註釋爲 "No object or array has been started"(還沒開始讀取對象或列表)
//6作爲常量保存在 JsonScope 中,JsonScope 中還保存了很多代表指令的常量,下列會用到
//stackSize 是 stack 的有效元素計數器,初始化時 stackSize = 1,即只有第一個元素是有效的
int peekStack = stack[stackSize - 1];
//JsonScope.EMPTY_ARRAY = 1
if (peekStack == JsonScope.EMPTY_ARRAY) {
//JsonScope.NONEMPTY_ARRAY = 2
stack[stackSize - 1] = JsonScope.NONEMPTY_ARRAY;
} else if (peekStack == JsonScope.NONEMPTY_ARRAY) {
//在第一次調用 nextNonWhitespace(true) 方法的時候,json 字符串會被轉存爲一個 char 數組
//該方法以 int 值的形式返回下一個要解析的 char 對象
int c = nextNonWhitespace(true);
switch (c) {
case ']':
//peeked 是 JsonReader 中最重要的用來狀態控制的 int 變量
//peeker 和 stack 會協同控制 JsonReader 的邏輯行爲
return peeked = PEEKED_END_ARRAY; //PEEKED_END_ARRAY = 4
case ';':
//檢查標準協議選項,json 標準中的符號沒有分號
//所以在 lenient = false 的時候就會報錯
checkLenient();
case ',':
break;
default:
throw syntaxError("Unterminated array");
}
//JsonScope.EMPTY_OBJECT = 3,JsonScope.NONEMPTY_OBJECT = 5
} else if (peekStack == JsonScope.EMPTY_OBJECT || peekStack == JsonScope.NONEMPTY_OBJECT) {
//JsonScope.DANGLING_NAME = 4
stack[stackSize - 1] = JsonScope.DANGLING_NAME;
if (peekStack == JsonScope.NONEMPTY_OBJECT) {
int c = nextNonWhitespace(true);
switch (c) {
case '}':
return peeked = PEEKED_END_OBJECT; //PEEKED_END_OBJECT = 2
case ';':
checkLenient();
case ',':
break;
default:
throw syntaxError("Unterminated object");
}
}
int c = nextNonWhitespace(true);
switch (c) {
case '"':
return peeked = PEEKED_DOUBLE_QUOTED_NAME; //PEEKED_DOUBLE_QUOTED_NAME = 13
case '\'':
checkLenient();
return peeked = PEEKED_SINGLE_QUOTED_NAME; //PEEKED_SINGLE_QUOTED_NAME = 12
case '}':
if (peekStack != JsonScope.NONEMPTY_OBJECT) {
return peeked = PEEKED_END_OBJECT;
} else {
throw syntaxError("Expected name");
}
default:
checkLenient();
pos--;
if (isLiteral((char) c)) {
return peeked = PEEKED_UNQUOTED_NAME; //PEEKED_UNQUOTED_NAME = 14
} else {
throw syntaxError("Expected name");
}
}
} else if (peekStack == JsonScope.DANGLING_NAME) {
stack[stackSize - 1] = JsonScope.NONEMPTY_OBJECT;
int c = nextNonWhitespace(true);
switch (c) {
case ':':
break;
case '=':
checkLenient();
//buffer 是儲存 json 字符串的 char 數組
//pos 是已經讀取到字符的數量指針
//limit 是 buffer 的可用部分的總長
if ((pos < limit || fillBuffer(1)) && buffer[pos] == '>') {
pos++;
}
break;
default:
throw syntaxError("Expected ':'");
}
//JsonScope.EMPTY_DOCUMENT = 6
//第一次進入方法的時候,會進入這個 if 語句中
} else if (peekStack == JsonScope.EMPTY_DOCUMENT) {
//檢查標準化協議相關
if (lenient) {
consumeNonExecutePrefix();
}
//JsonScope.NONEMPTY_DOCUMENT = 7
stack[stackSize - 1] = JsonScope.NONEMPTY_DOCUMENT;
} else if (peekStack == JsonScope.NONEMPTY_DOCUMENT) {
int c = nextNonWhitespace(false);
if (c == -1) {
return peeked = PEEKED_EOF;
} else {
checkLenient();
pos--;
}
//JsonScope.CLOSED = 8
} else if (peekStack == JsonScope.CLOSED) {
throw new IllegalStateException("JsonReader is closed");
}
//在這裏獲取到了下一個要解析的 char 的 int 值
int c = nextNonWhitespace(true);
//進入 switch 去進行定位,定位到了之後修改 peeked 的狀態
switch (c) {
case ']':
if (peekStack == JsonScope.EMPTY_ARRAY) {
return peeked = PEEKED_END_ARRAY;
}
case ';':
case ',':
if (peekStack == JsonScope.EMPTY_ARRAY || peekStack == JsonScope.NONEMPTY_ARRAY) {
checkLenient();
pos--;
return peeked = PEEKED_NULL;
} else {
throw syntaxError("Unexpected value");
}
case '\'':
checkLenient();
return peeked = PEEKED_SINGLE_QUOTED;
case '"':
return peeked = PEEKED_DOUBLE_QUOTED;
case '[':
return peeked = PEEKED_BEGIN_ARRAY;
case '{':
return peeked = PEEKED_BEGIN_OBJECT;
default:
pos--;
}
//peekKeyword() 方法會從 buffer 數組裏獲取下一個 char
//然後根據這個字符判斷下一個要處理的字符串是不是 true、false、null 等特殊字符
//如果不是,會返回 result = PEEKED_NONE
int result = peekKeyword();
if (result != PEEKED_NONE) {
//不等於 PEEKED_NONE,證明下一個確實是特殊字符
return result;
}
//peekNumber() 方法和上述 peekKeyword() 方法很類似
//用於判斷下一個要處理的字符串是否是數字
result = peekNumber();
if (result != PEEKED_NONE) {
return result;
}
//isLiteral(buffer[pos]) 用於判斷下一個字符是否是特殊符
//比如 換行符、井號、括號 等
//如果是 換行符 的話這裏就會拋出錯誤
if (!isLiteral(buffer[pos])) {
throw syntaxError("Expected value");
}
checkLenient();
return peeked = PEEKED_UNQUOTED; //PEEKED_UNQUOTED = 10
}
beginObject()
public void beginObject() throws IOException {
int p = peeked;
//初始化時 peeked = PEEKED_NONE
//在 doPeek() 方法中會修改成 PEEKED_BEGIN_OBJECT,即開始一個 Object 的序列化
if (p == PEEKED_NONE) {
p = doPeek();
}
if (p == PEEKED_BEGIN_OBJECT) {
//push(...) 方法會檢查 stack 數組的容積,適時進行擴容,並把傳入的指令存放到數組中
//此處將 EMPTY_OBJECT 指令存入到 stack 中
push(JsonScope.EMPTY_OBJECT);
//將 peeked 狀態初始化
peeked = PEEKED_NONE;
} else {
throw new IllegalStateException("Expected BEGIN_OBJECT but was " + peek() + locationString());
}
}
nextName()
public String nextName() throws IOException {
//老樣子進行 peeked 的狀態獲取
int p = peeked;
if (p == PEEKED_NONE) {
p = doPeek();
}
String result;
//在這裏通過 if 語句和 peeked 定位 json 的 key 是用單引號還是雙引號包裹的
//result 就是 key 的字符串
if (p == PEEKED_UNQUOTED_NAME) {
result = nextUnquotedValue();
} else if (p == PEEKED_SINGLE_QUOTED_NAME) {
result = nextQuotedValue('\'');
} else if (p == PEEKED_DOUBLE_QUOTED_NAME) {
result = nextQuotedValue('"');
} else {
throw new IllegalStateException("Expected a name but was " + peek() + locationString());
}
//將 peeked 狀態初始化
peeked = PEEKED_NONE;
//pathNames 是一個用來儲存所有 key 的字符串的數組
pathNames[stackSize - 1] = result;
return result;
}
到此反序列化源碼學習完成了。
參考:
https://segmentfault.com/a/1190000017868423?utm_source=tag-newest
https://www.jianshu.com/p/da21b3a59b47