亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

追蹤解析Gson源碼(2)

shiguibiao / 2412人閱讀

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

接上篇 三 JsonReader 和 JsonWriter

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

1 JsonReader

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

在 Gson 包中可以不使用 Gson 門面而多帶帶使用 JsonReader 進(jìn)行 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);
    //創(chuàng)建一個(gè)參數(shù)均為空的目標(biāo)對(duì)象
    Person p = new Person();
    try {
        //beginObject(...) 方法用于告訴 jsonReader 開始讀取一個(gè) object
        jsonReader.beginObject();
        //while 循環(huán)讀取
        while(jsonReader.hasNext()){
            //讀取一個(gè) json 的 key 值
            String name = jsonReader.nextName();
            switch (name){
                case "name": 
                    p.setName(jsonReader.nextString()); //讀取一個(gè) String 作為 value,存入對(duì)象中
                    break;
                case "age": 
                    p.setAge(jsonReader.nextInt()); //讀取一個(gè) int 作為 value,存入對(duì)象中
                    break;
            }
        }
        jsonReader.endObject();
    } catch (IOException e) {
        e.printStackTrace();
    }
    System.out.println("名字:" + p.getName());
    System.out.println("年齡:"  +p.getAge())
}

JsonReader 的構(gòu)造方法:

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

JsonReader 僅此一個(gè)構(gòu)造方法,創(chuàng)建對(duì)象均調(diào)用此方法。

先來(lái)看一下 JsonReader 中非常重要的一個(gè)非公開方法 doPeek():

//JsonReader.class
int doPeek() throws IOException {
    //stack 是一個(gè)定義在 JsonReader 中的 int 數(shù)組,作為 JsonReader 的指令集存在,用于控制變量 peeked 的狀態(tài)
    //在 JsonReader 初始化的時(shí)候會(huì)將 stack 的第一個(gè)元素變成6,其余均為0
    //6的意思根據(jù)官方注釋為 "No object or array has been started"(還沒開始讀取對(duì)象或列表)
    //6作為常量保存在 JsonScope 中,JsonScope 中還保存了很多代表指令的常量,下列會(huì)用到
    //stackSize 是 stack 的有效元素計(jì)數(shù)器,初始化時(shí) stackSize = 1,即只有第一個(gè)元素是有效的
    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) {
        //在第一次調(diào)用 nextNonWhitespace(true) 方法的時(shí)候,json 字符串會(huì)被轉(zhuǎn)存為一個(gè) char 數(shù)組
        //該方法以 int 值的形式返回下一個(gè)要解析的 char 對(duì)象
        int c = nextNonWhitespace(true);
        switch (c) {
            case "]":
                //peeked 是 JsonReader 中最重要的用來(lái)狀態(tài)控制的 int 變量
                //peeker 和 stack 會(huì)協(xié)同控制 JsonReader 的邏輯行為
                return peeked = PEEKED_END_ARRAY; //PEEKED_END_ARRAY = 4
            case ";":
                 //檢查標(biāo)準(zhǔn)協(xié)議選項(xiàng),json 標(biāo)準(zhǔn)中的符號(hào)沒有分號(hào)
                //所以在 lenient = false 的時(shí)候就會(huì)報(bào)錯(cuò)
                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 是儲(chǔ)存 json 字符串的 char 數(shù)組
                //pos 是已經(jīng)讀取到字符的數(shù)量指針
                //limit 是 buffer 的可用部分的總長(zhǎng)
                if ((pos < limit || fillBuffer(1)) && buffer[pos] == ">") {
                    pos++;
                }
                break;
            default:
                throw syntaxError("Expected ":"");
        }
        //JsonScope.EMPTY_DOCUMENT = 6
        //第一次進(jìn)入方法的時(shí)候,會(huì)進(jìn)入這個(gè) if 語(yǔ)句中
    } else if (peekStack == JsonScope.EMPTY_DOCUMENT) {
        //檢查標(biāo)準(zhǔn)化協(xié)議相關(guān)
        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");
    }

    //在這里獲取到了下一個(gè)要解析的 char 的 int 值
    int c = nextNonWhitespace(true);
    //進(jìn)入 switch 去進(jìn)行定位,定位到了之后修改 peeked 的狀態(tài)
    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() 方法會(huì)從 buffer 數(shù)組里獲取下一個(gè) char
    //然后根據(jù)這個(gè)字符判斷下一個(gè)要處理的字符串是不是 true、false、null 等特殊字符
    //如果不是,會(huì)返回 result = PEEKED_NONE
    int result = peekKeyword();
    if (result != PEEKED_NONE) {
        //不等于 PEEKED_NONE,證明下一個(gè)確實(shí)是特殊字符
        return result;
    }

    //peekNumber() 方法和上述 peekKeyword() 方法很類似
    //用于判斷下一個(gè)要處理的字符串是否是數(shù)字
    result = peekNumber();
    if (result != PEEKED_NONE) {
        return result;
    }

    //isLiteral(buffer[pos]) 用于判斷下一個(gè)字符是否是特殊符
    //比如 換行符、井號(hào)、括號(hào) 等
    //如果是 換行符 的話這里就會(huì)拋出錯(cuò)誤
    if (!isLiteral(buffer[pos])) {
        throw syntaxError("Expected value");
    }

    checkLenient();
    return peeked = PEEKED_UNQUOTED; //PEEKED_UNQUOTED = 10
}

方法雖然比較長(zhǎng),但是代碼其實(shí)比較簡(jiǎn)單,本質(zhì)上是根據(jù) stack 指令去修改 peeked 的值,從而達(dá)到狀態(tài)控制的效果。

再來(lái)看 beginObject() 方法:

//JsonReader.class
public void beginObject() throws IOException {
    int p = peeked;

    //初始化時(shí) peeked = PEEKED_NONE
    //在 doPeek() 方法中會(huì)修改成 PEEKED_BEGIN_OBJECT,即開始一個(gè) Object 的序列化
    if (p == PEEKED_NONE) {
          p = doPeek();
    }
    if (p == PEEKED_BEGIN_OBJECT) {
        //push(...) 方法會(huì)檢查 stack 數(shù)組的容積,適時(shí)進(jìn)行擴(kuò)容,并把傳入的指令存放到數(shù)組中
        //此處將 EMPTY_OBJECT 指令存入到 stack 中
        push(JsonScope.EMPTY_OBJECT);
        //將 peeked 狀態(tài)初始化
        peeked = PEEKED_NONE;
    } else {
          throw new IllegalStateException("Expected BEGIN_OBJECT but was " + peek() + locationString());
    }
}

再來(lái)看 nextName() 方法:

//JsonReader.class
public String nextName() throws IOException {
    //老樣子進(jìn)行 peeked 的狀態(tài)獲取
    int p = peeked;
    if (p == PEEKED_NONE) {
      p = doPeek();
    }
    String result;
    
    //在這里通過(guò) if 語(yǔ)句和 peeked 定位 json 的 key 是用單引號(hào)還是雙引號(hào)包裹的
    //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 狀態(tài)初始化
    peeked = PEEKED_NONE;
    //pathNames 是一個(gè)用來(lái)儲(chǔ)存所有 key 的字符串的數(shù)組
    pathNames[stackSize - 1] = result;
    return result;
}

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

hasNext() 和 nextString() 方法其實(shí)都和 nextName() 方法差不多,本質(zhì)上都是根據(jù) peeked 的值去進(jìn)入不同的 if 語(yǔ)句來(lái)處理字符串。

2 JsonWriter

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

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

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

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

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

JsonWriter 的構(gòu)造方法:

//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 {
    //這個(gè)方法主要的作用是在不同的 object 之間加逗號(hào)
    //如果是起始第一個(gè) object 就不需要了,會(huì)直接跳過(guò)
    writeDeferredName();
    return open(EMPTY_OBJECT, "{");
}

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

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

JsonWriter 中沒有 JsonReader 中那么復(fù)雜的指令操作,所以沒有引入 peeked 變量,僅僅使用 stack 數(shù)組來(lái)控制狀態(tài)。

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

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

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

來(lái)看一下 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.");
    }
    //這一行代碼中會(huì)暫時(shí)將傳入的 name 參數(shù)保存在一個(gè)全局變量中,
    //所以 JsonWriter 在調(diào)用 value(...) 方法之前不能再調(diào)用 name(...) 方法了,不然在上方的判斷中會(huì)報(bào)錯(cuò)
    deferredName = name;
    return this;
}

來(lái)看一下 value(...) 方法:

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

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

總的來(lái)說(shuō) JsonWriter 比 JsonReader 簡(jiǎn)單,簡(jiǎn)要描述一下不過(guò)多展開。

四 JSON 字符串轉(zhuǎn) Bean

該 part 的起點(diǎn):

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

追蹤 fromJson(...) 方法:

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

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

先來(lái)看一下上述的第二行代碼:

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

Primitives.wrap(...) 方法的實(shí)現(xiàn):

//Primitives.class
public static  Class wrap(Class type) {
    //PRIMITIVE_TO_WRAPPER_TYPE 是一個(gè) map 對(duì)象
    //$Gson$Preconditions.checkNotNull(...) 用來(lái)效驗(yàn) 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 是一個(gè)定義在 Primitives 中的 map 對(duì)象:

//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);

    //以下代碼是將原始類型和包裝類型存入兩個(gè) map 的過(guò)程
    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(...) 返回一個(gè)只能閱讀不能修改的 map
    //原始類型作為 key,包裝類型作為 value
    PRIMITIVE_TO_WRAPPER_TYPE = Collections.unmodifiableMap(primToWrap);
    //包裝類型作為 value,原始類型作為 key
    WRAPPER_TO_PRIMITIVE_TYPE = Collections.unmodifiableMap(wrapToPrim);
}

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

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

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

代碼比較簡(jiǎn)單,本質(zhì)上就是強(qiáng)轉(zhuǎn)類型。

再來(lái)看這行代碼:

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

追蹤具體實(shí)現(xiàn):

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

繼續(xù)追蹤重載方法:

//Gson.class
public  T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
    //初始化一個(gè) JsonReader
    JsonReader jsonReader = newJsonReader(json);
    //主體功能實(shí)現(xiàn)方法
    T object = (T) fromJson(jsonReader, typeOfT);
    //在整個(gè)反序列化過(guò)程結(jié)束之前效驗(yàn) jsonReader 的 peeked 的狀態(tài)
    //如果 peeker 未處于結(jié)束狀態(tài),則會(huì)報(bào)錯(cuò)
    assertFullConsumption(object, jsonReader);
    return object;
}

繼續(xù)追蹤重載方法:

//Gson.class
public  T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
    boolean isEmpty = true;
    boolean oldLenient = reader.isLenient();
    //打開 reader 的標(biāo)準(zhǔn)化檢驗(yàn)
    reader.setLenient(true);
    try {
        //此處相當(dāng)于調(diào)用了一次 JsonReader 中的 doPeek() 方法
        reader.peek();
        isEmpty = false;
        //TypeToken 本質(zhì)上是 Class 的增強(qiáng)封裝類
        TypeToken typeToken = (TypeToken) TypeToken.get(typeOfT);
        //根據(jù) TypeToken 獲取對(duì)應(yīng)的能夠處理其類型的 TypeAdapter
        TypeAdapter typeAdapter = getAdapter(typeToken);
        //反射創(chuàng)建 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);
    }
}

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

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

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

    //如果存在對(duì)象,就會(huì)在這里取用出來(lái)并返回
    //FutureTypeAdapter 是一個(gè)門面模式的應(yīng)用,其實(shí)本質(zhì)是使用內(nèi)部的 TypeAdapter 去處理業(yè)務(wù)
    //如果內(nèi)部沒有存入實(shí)際處理業(yè)務(wù)的 TypeAdapter,就會(huì)報(bào)錯(cuò)
    FutureTypeAdapter ongoingCall = (FutureTypeAdapter) threadCalls.get(type);
    if (ongoingCall != null) {
      return ongoingCall;
    }

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

        //這個(gè)方法的主體是這個(gè) for 循環(huán),用于從 Gson 初始化的時(shí)候儲(chǔ)存的列表中獲取到對(duì)應(yīng)的 TypeAdapter
        for (TypeAdapterFactory factory : factories) {
            //TypeAdapter 的 create(...) 方法對(duì)于不是對(duì)應(yīng)類型的參數(shù)會(huì)返回 null
            TypeAdapter candidate = factory.create(this, type);
            if (candidate != null) {
                //在此處會(huì)存入業(yè)務(wù)處理的 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 轉(zhuǎn) JSON 字符串

該 part 的起點(diǎn):

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) 方法最后會(huì)輸出一個(gè) null 字符串,不多展開了。

繼續(xù)來(lái)關(guān)注下方主要實(shí)現(xiàn)邏輯:

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

繼續(xù)追蹤主要邏輯方法:

//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);
    }
}

繼續(xù)追蹤主要邏輯方法:

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

    //下方代碼均為儲(chǔ)存并存入一些標(biāo)準(zhǔn)化的設(shè)置
    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);
    }
}

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

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

四 總結(jié)

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

總結(jié)一下 Gson 的基本思路:

· 解析器(Gson)將使用者傳入的字符串或?qū)ο蟠嫒胱x取器(Reader)或者寫入器(Writer)中

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

· 適配器工廠會(huì)創(chuàng)建出對(duì)應(yīng)類型的適配器(TypeAdapter)

· 解析器將閱讀器或?qū)懭肫鹘唤o適配器

· 適配器自行通過(guò)業(yè)務(wù)邏輯操作讀取器或?qū)懭肫?,輸出需要的結(jié)果

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

五 一點(diǎn)嘮叨

· Gson 太過(guò)強(qiáng)調(diào)功能的全面,解析器的初始化非常復(fù)雜

· JsonReader 的狀態(tài)控制太過(guò)復(fù)雜和精密,筆者到現(xiàn)在也沒全部弄清楚

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

· 僅為個(gè)人的學(xué)習(xí)筆記,可能存在錯(cuò)誤或者表述不清的地方,有緣補(bǔ)充

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/72959.html

相關(guān)文章

  • 追蹤解析Gson源碼(1)

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

    sewerganger 評(píng)論0 收藏0
  • 追蹤解析 ThreadPoolExecutor 源碼

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

    gaomysion 評(píng)論0 收藏0
  • Retrofit源碼分析

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

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

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

    oujie 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<