国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

追蹤解析Gson源碼(2)

shiguibiao / 2353人閱讀

摘要:接上篇三和在進行的序列化和反序列化源碼解析之前先了解一下其主體工具類。是中用于序列化的主體。同時為了兼顧性能做了很多有意思的設計,比如獲取適配器的時候的雙緩存設計,應該是為了提高解析器的復用效率,具體有待研究。

接上篇 三 JsonReader 和 JsonWriter

在進行 json 的序列化和反序列化源碼解析之前先了解一下其主體工具類。

1 JsonReader

JsonReader 是 Gson 中用于 json 反序列化的主體。

在 Gson 包中可以不使用 Gson 門面而多帶帶使用 JsonReader 進行 json 的反序列化:

public static void main(String[] args){
    //json 字符串
    String json = "{"name":"zhangsan","age":18}";
    //使用 StringReader 包裝字符串
    StringReader strReader = new StringReader(json);
    //使用 JsonReader 包裝 StringReader
    JsonReader jsonReader = new JsonReader(strReader);
    //創建一個參數均為空的目標對象
    Person p = new Person();
    try {
        //beginObject(...) 方法用于告訴 jsonReader 開始讀取一個 object
        jsonReader.beginObject();
        //while 循環讀取
        while(jsonReader.hasNext()){
            //讀取一個 json 的 key 值
            String name = jsonReader.nextName();
            switch (name){
                case "name": 
                    p.setName(jsonReader.nextString()); //讀取一個 String 作為 value,存入對象中
                    break;
                case "age": 
                    p.setAge(jsonReader.nextInt()); //讀取一個 int 作為 value,存入對象中
                    break;
            }
        }
        jsonReader.endObject();
    } catch (IOException e) {
        e.printStackTrace();
    }
    System.out.println("名字:" + p.getName());
    System.out.println("年齡:"  +p.getAge())
}

JsonReader 的構造方法:

//JsonReader.class
public JsonReader(Reader in) {
    if (in == null) {
        throw new NullPointerException("in == null");
    }
    //傳入的 Reader 中保存著要讀取的 json 主體 
    //此處比較常用的是 StringReader,但是也可以是 FileReader 等其它 Reader 接口的實現類
    this.in = in;
}

JsonReader 僅此一個構造方法,創建對象均調用此方法。

先來看一下 JsonReader 中非常重要的一個非公開方法 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
}

方法雖然比較長,但是代碼其實比較簡單,本質上是根據 stack 指令去修改 peeked 的值,從而達到狀態控制的效果。

再來看 beginObject() 方法:

//JsonReader.class
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() 方法:

//JsonReader.class
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;
}

nextQuotedValue(...) 方法里實際上是比較繁瑣的字符串處理,在這里暫時不展開了。

hasNext() 和 nextString() 方法其實都和 nextName() 方法差不多,本質上都是根據 peeked 的值去進入不同的 if 語句來處理字符串。

2 JsonWriter

JsonWriter 是 Gson 中用于 json 序列化的主體。

和 JsonReader 一樣,也可以不使用 Gson 門面而多帶帶使用 JsonWriter 進行 json 的序列化:

public static void main(String[] args){
    //組裝 bean
    Person person = new Person();
    person.setName("zhangsan");
    person.setAge(18);

    //創建一個 StringWriter,本質是 StringBuffer 的封裝
    StringWriter writer = new StringWriter();
    //用 JsonWriter 去封裝 StringWriter
    JsonWriter jsonWriter = new JsonWriter(writer);
    try {
        //啟動一個 object 的寫入
        jsonWriter.beginObject();
        //寫入 key-value
        jsonWriter.name("name").value(person.getName());
        jsonWriter.name("age").value(person.getAge());
        //結束命令
        jsonWriter.endObject();
        //將 JsonWriter 里的數據存入到 StringWriter 中
        jsonWriter.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }

    System.out.println(writer.toString());
}

JsonWriter 的構造方法:

//JsonWriter.class
public JsonWriter(Writer out) {
    if (out == null) {
        throw new NullPointerException("out == null");
    }
    this.out = out;
}

追蹤一下 beginObject() 方法:

//JsonWriter.class
public JsonWriter beginObject() throws IOException {
    //這個方法主要的作用是在不同的 object 之間加逗號
    //如果是起始第一個 object 就不需要了,會直接跳過
    writeDeferredName();
    return open(EMPTY_OBJECT, "{");
}

繼續追蹤 open(...) 方法:

//JsonWriter.class
private JsonWriter open(int empty, String openBracket) throws IOException {
    //該方法會使用 stack 中最新的指令進行操作
    beforeValue();
    //push(...) 方法會檢查 stack 數組的容積,適時進行擴容,并把傳入的指令存放到數組中
    push(empty);
    //寫入字符串
    out.write(openBracket);
    return this;
}

JsonWriter 中沒有 JsonReader 中那么復雜的指令操作,所以沒有引入 peeked 變量,僅僅使用 stack 數組來控制狀態。

stack 的控制封裝在 beforeValue() 方法中:

//JsonWriter.class
private void beforeValue() throws IOException {
    //peek() 方法會根據 stack 數組的指令獲取到下一個要操作的字符類型
    switch (peek()) {
        case NONEMPTY_DOCUMENT:
            if (!lenient) {
            throw new IllegalStateException(
                "JSON must have only one top-level value.");
            }
        case EMPTY_DOCUMENT:
            //replaceTop(...) 方法會將 stack 最新的指令更新成傳入的參數
            replaceTop(NONEMPTY_DOCUMENT);
            break;

        case EMPTY_ARRAY:
            replaceTop(NONEMPTY_ARRAY);
            //換行
            newline();
            break;
        case NONEMPTY_ARRAY:
            out.append(",");
            newline();
            break;
        case DANGLING_NAME:
            //separator 即為 ":" (冒號)
            out.append(separator);
            replaceTop(NONEMPTY_OBJECT);
            break;
        default:
            throw new IllegalStateException("Nesting problem.");
        }
}

來看一下 name(...) 方法:

//JsonWriter.class
public JsonWriter name(String name) throws IOException {
    if (name == null) {
      throw new NullPointerException("name == null");
    }
    if (deferredName != null) {
      throw new IllegalStateException();
    }
    if (stackSize == 0) {
      throw new IllegalStateException("JsonWriter is closed.");
    }
    //這一行代碼中會暫時將傳入的 name 參數保存在一個全局變量中,
    //所以 JsonWriter 在調用 value(...) 方法之前不能再調用 name(...) 方法了,不然在上方的判斷中會報錯
    deferredName = name;
    return this;
}

來看一下 value(...) 方法:

//JsonWriter.class
public JsonWriter value(String value) throws IOException {

    if (value == null) {
        //nullValue() 方法會在 value 值的地方存入一個 null
          return nullValue();
    }
    //這一方法會將 之前保存在 deferredName 中的字符串寫入到 writer 中
    //方法中會處理加逗號、將 deferredName 變量清空等問題
    //核心是調用 string(...) 方法寫入
    writeDeferredName();
    //更新 stack 指令
    beforeValue();
    //和上方寫入 deferredName 一樣,此處調用寫入 value
    string(value);
    return this;
  }

總的來說 JsonWriter 比 JsonReader 簡單,簡要描述一下不過多展開。

四 JSON 字符串轉 Bean

該 part 的起點:

Person person = gson.fromJson(json,Person.class);

追蹤 fromJson(...) 方法:

//Gson.class
public  T fromJson(String json, Class classOfT) throws JsonSyntaxException {
    //將字符串轉成 object 的主體方法
    //3.1
    Object object = fromJson(json, (Type) classOfT);

    return Primitives.wrap(classOfT).cast(object);
}

先來看一下上述的第二行代碼:

return Primitives.wrap(classOfT).cast(object);

Primitives.wrap(...) 方法的實現:

//Primitives.class
public static  Class wrap(Class type) {
    //PRIMITIVE_TO_WRAPPER_TYPE 是一個 map 對象
    //$Gson$Preconditions.checkNotNull(...) 用來效驗 type 不為空
    @SuppressWarnings("unchecked")
    Class wrapped = (Class) PRIMITIVE_TO_WRAPPER_TYPE.get(
        $Gson$Preconditions.checkNotNull(type));
    //如果 map 中不存在 type 為 key 的值,則返回 type,否則返回取到的 value
    return (wrapped == null) ? type : wrapped;
}

PRIMITIVE_TO_WRAPPER_TYPE 是一個定義在 Primitives 中的 map 對象:

//Primitives.class
private static final Map, Class> PRIMITIVE_TO_WRAPPER_TYPE;

PRIMITIVE_TO_WRAPPER_TYPE 中主要存放了 float、int、double 等原始類型的 class:

//Primitives.class
static {
    Map, Class> primToWrap = new HashMap, Class>(16);
    Map, Class> wrapToPrim = new HashMap, Class>(16);

    //以下代碼是將原始類型和包裝類型存入兩個 map 的過程
    add(primToWrap, wrapToPrim, boolean.class, Boolean.class);
    add(primToWrap, wrapToPrim, byte.class, Byte.class);
    add(primToWrap, wrapToPrim, char.class, Character.class);
    add(primToWrap, wrapToPrim, double.class, Double.class);
    add(primToWrap, wrapToPrim, float.class, Float.class);
    add(primToWrap, wrapToPrim, int.class, Integer.class);
    add(primToWrap, wrapToPrim, long.class, Long.class);
    add(primToWrap, wrapToPrim, short.class, Short.class);
    add(primToWrap, wrapToPrim, void.class, Void.class);

    //Collections.unmodifiableMap(...) 返回一個只能閱讀不能修改的 map
    //原始類型作為 key,包裝類型作為 value
    PRIMITIVE_TO_WRAPPER_TYPE = Collections.unmodifiableMap(primToWrap);
    //包裝類型作為 value,原始類型作為 key
    WRAPPER_TO_PRIMITIVE_TYPE = Collections.unmodifiableMap(wrapToPrim);
}

由此可見 Primitives.wrap(...) 本質上是判斷傳入的 type 是否是原始類型,如果是,則會轉換成包裝類型并返回。

至于 Primitives.wrap(classOfT).cast(object) 中的 cast(...),則是定義在 Class 中的方法:

//Class.class
@HotSpotIntrinsicCandidate
public T cast(Object obj) {
    //isInstance(...) 方法等價于關鍵詞 instanceof
    //如果 obj 不為 null 且 不為該 Class 對象的子類,則會拋出錯誤
    if (obj != null && !isInstance(obj))
        throw new ClassCastException(cannotCastMsg(obj));
    return (T) obj;
}

代碼比較簡單,本質上就是強轉類型。

再來看這行代碼:

Object object = fromJson(json, (Type) classOfT);

追蹤具體實現:

//Gson.class
public  T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
    //非 null 判斷
    if (json == null) {
      return null;
    }
    //StringReader 是一個 jdk 中存在的 String 和 Reader 的關聯封裝類
    StringReader reader = new StringReader(json);
    //主體功能實現方法
    T target = (T) fromJson(reader, typeOfT);
    //返回一個指定泛型的對象
    return target;
}

繼續追蹤重載方法:

//Gson.class
public  T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
    //初始化一個 JsonReader
    JsonReader jsonReader = newJsonReader(json);
    //主體功能實現方法
    T object = (T) fromJson(jsonReader, typeOfT);
    //在整個反序列化過程結束之前效驗 jsonReader 的 peeked 的狀態
    //如果 peeker 未處于結束狀態,則會報錯
    assertFullConsumption(object, jsonReader);
    return object;
}

繼續追蹤重載方法:

//Gson.class
public  T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
    boolean isEmpty = true;
    boolean oldLenient = reader.isLenient();
    //打開 reader 的標準化檢驗
    reader.setLenient(true);
    try {
        //此處相當于調用了一次 JsonReader 中的 doPeek() 方法
        reader.peek();
        isEmpty = false;
        //TypeToken 本質上是 Class 的增強封裝類
        TypeToken typeToken = (TypeToken) TypeToken.get(typeOfT);
        //根據 TypeToken 獲取對應的能夠處理其類型的 TypeAdapter
        TypeAdapter typeAdapter = getAdapter(typeToken);
        //反射創建 object
        T object = typeAdapter.read(reader);
        return object;
    } catch (EOFException e) {
        if (isEmpty) {
            return null;
        }
        throw new JsonSyntaxException(e);
    } catch (IllegalStateException e) {
          throw new JsonSyntaxException(e);
    } catch (IOException e) {
        throw new JsonSyntaxException(e);
    } catch (AssertionError e) {
          throw new AssertionError("AssertionError (GSON " + GsonBuildConfig.VERSION + "): " + e.getMessage(), e);
    } finally {
          reader.setLenient(oldLenient);
    }
}

先來看一下 getAdapter(...) 方法:

//Gson.class
public  TypeAdapter getAdapter(TypeToken type) {
    //typeTokenCache 是 Gson 中的一個 map 對象,用于儲存 TypeAdapter
    //typeTokenCache 是一個 Gson 中各個線程公用的一個緩存池
    TypeAdapter cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);
    if (cached != null) {
        //如果本身就有儲存了,就直接返回
          return (TypeAdapter) cached;
    }

    //calls 是一個 ThreadLocal 對象
    //ThreadLocal 是 Gson 中單個線程使用的緩存池,在里面存入的對象會在 finally 代碼塊中清空掉
    Map, FutureTypeAdapter> threadCalls = calls.get();
    //判斷是否需要清空 ThreadLocal
    boolean requiresThreadLocalCleanup = false;
    if (threadCalls == null) {
        threadCalls = new HashMap, FutureTypeAdapter>();
        calls.set(threadCalls);
        //這里存入了對象,所以需要清空 ThreadLocal
        requiresThreadLocalCleanup = true;
    }

    //如果存在對象,就會在這里取用出來并返回
    //FutureTypeAdapter 是一個門面模式的應用,其實本質是使用內部的 TypeAdapter 去處理業務
    //如果內部沒有存入實際處理業務的 TypeAdapter,就會報錯
    FutureTypeAdapter ongoingCall = (FutureTypeAdapter) threadCalls.get(type);
    if (ongoingCall != null) {
      return ongoingCall;
    }

    try {
        FutureTypeAdapter call = new FutureTypeAdapter();
        threadCalls.put(type, call);

        //這個方法的主體是這個 for 循環,用于從 Gson 初始化的時候儲存的列表中獲取到對應的 TypeAdapter
        for (TypeAdapterFactory factory : factories) {
            //TypeAdapter 的 create(...) 方法對于不是對應類型的參數會返回 null
            TypeAdapter candidate = factory.create(this, type);
            if (candidate != null) {
                //在此處會存入業務處理的 TypeAdapter
                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();
        }
    }
}

到此為止 json 的反序列化就基本完畢了.

五 Bean 轉 JSON 字符串

該 part 的起點:

String json2 = gson.toJson(person);

追蹤 toJson(...) 方法:

//Gson.class
public String toJson(Object src) {
    if (src == null) {
      return toJson(JsonNull.INSTANCE);
    }
    return toJson(src, src.getClass());
}

toJson(JsonNull.INSTANCE) 方法最后會輸出一個 null 字符串,不多展開了。

繼續來關注下方主要實現邏輯:

//Gson.class
public String toJson(Object src, Type typeOfSrc) {
    //新建一個 StringWriter
    StringWriter writer = new StringWriter();
    //主要邏輯
    toJson(src, typeOfSrc, writer);
    //返回
    return writer.toString();
}

繼續追蹤主要邏輯方法:

//Gson.class
public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOException {
    try {
        //這里將 StringWriter 包裝成了 JsonWriter
        JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer));
        //主要邏輯
        toJson(src, typeOfSrc, jsonWriter);
    } catch (IOException e) {
          throw new JsonIOException(e);
    }
}

繼續追蹤主要邏輯方法:

//Gson.class
public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException {
    //獲取適配的 TypeAdapter
    TypeAdapter adapter = getAdapter(TypeToken.get(typeOfSrc));

    //下方代碼均為儲存并存入一些標準化的設置
    boolean oldLenient = writer.isLenient();
    writer.setLenient(true);
    boolean oldHtmlSafe = writer.isHtmlSafe();
    writer.setHtmlSafe(htmlSafe);
    boolean oldSerializeNulls = writer.getSerializeNulls();
    writer.setSerializeNulls(serializeNulls);

    //寫入
    try {
        ((TypeAdapter) adapter).write(writer, src);
    } catch (IOException e) {
          throw new JsonIOException(e);
    } catch (AssertionError e) {
          throw new AssertionError("AssertionError (GSON " + GsonBuildConfig.VERSION + "): " + e.getMessage(), e);
    } finally {
        //還原
          writer.setLenient(oldLenient);
          writer.setHtmlSafe(oldHtmlSafe);
          writer.setSerializeNulls(oldSerializeNulls);
    }
}

基本的邏輯都在上面講過了,不贅述。

到此為止 json 的序列化就基本完畢了。

四 總結

Gson 的代碼封裝很薄,本身不難,但是為了照顧兼容性,代碼中存在很多條件判斷,導致代碼看上去很繁瑣。同時為了兼顧性能做了很多有意思的設計,比如獲取適配器的時候的雙緩存設計,應該是為了提高解析器的復用效率,具體有待研究。

總結一下 Gson 的基本思路:

· 解析器(Gson)將使用者傳入的字符串或對象存入讀取器(Reader)或者寫入器(Writer)中

· 解析器遍歷并獲取能夠處理對應類型的適配器工廠(TypeAdapterFactory)

· 適配器工廠會創建出對應類型的適配器(TypeAdapter)

· 解析器將閱讀器或寫入器交給適配器

· 適配器自行通過業務邏輯操作讀取器或寫入器,輸出需要的結果

· 解析器接收此輸出,并交給使用者

五 一點嘮叨

· Gson 太過強調功能的全面,解析器的初始化非常復雜

· JsonReader 的狀態控制太過復雜和精密,筆者到現在也沒全部弄清楚

· 在本篇源碼解析中,Gson 內部還有一些拓展功能,比如 JsonElement、JsonParser 等的工具類沒有提及

· 僅為個人的學習筆記,可能存在錯誤或者表述不清的地方,有緣補充

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/72959.html

相關文章

  • 追蹤解析Gson源碼(1)

    摘要:版本版本簡介是谷歌開源的解析工具。其實幾款產品的差別都很細微,有谷歌的信仰加成,所以在這里進行一次源碼分析。至于和會在后續進行追蹤。 零 前期準備 0 FBI WARNING 文章異常啰嗦且繞彎。 1 版本 Gson 版本 : gson 2.8.5 IDE : idea 2018.3 2 Gson 簡介 Gson 是谷歌開源的 java json 解析工具。市場上同類的開源產品還有 F...

    sewerganger 評論0 收藏0
  • 追蹤解析 ThreadPoolExecutor 源碼

    摘要:的前位數用來表示線程的數量,后面三位用來表示線程池的狀態。線程池的狀態有五種,分別是,根據單詞就能猜出大概。并且為了考慮性能問題,線程池的設計沒有使用悲觀鎖關鍵字,而是大量使用了和機制。 零 前期準備 0 FBI WARNING 文章異常啰嗦且繞彎。 1 版本 JDK 版本 : OpenJDK 11.0.1 IDE : idea 2018.3 2 ThreadPoolExecutor ...

    gaomysion 評論0 收藏0
  • Retrofit源碼分析

    摘要:看下圖所示,摘自網絡的創建流程源碼分析實例是使用建造者模式通過類進行創建的。創建了一個含有對象實例的,并返回給源碼分析添加一個調用適配器工廠,用于支持服務方法返回類型注意生產的是,那么又是什么呢可以看到源代碼如下所示,它是一個接口。 目錄介紹 1.首先回顧Retrofit簡單使用方法 2.Retrofit的創建流程源碼分析 2.1 Retrofit對象調用Builder()源碼解...

    zero 評論0 收藏0
  • gson-plugin深入源碼分析(三)

    摘要:六修改內部類的方法這個的方法是對類型的數據進行解析,我們判斷輸入的數據類型不是類型,就直接跳過解析,核心是在方法中插入方法。每一個類每一個內部類每一個匿名內部類,都會生成一個獨立的文件,如。 一、項目地址 項目地址:github-gson-plugin 二、ReaderTools解析 /** * Created by tangfuling on 2018/10/23. */ pu...

    oujie 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<