com.alibaba.fastjson 序列化 反序列

                                  fastjson  序列化 反序列

目錄

                                  fastjson  序列化 反序列

序列化

SerializeWriter成員變量

一 SerializeWriter成員函數

1 序列化整形數字

2 序列化長整形數字

3 序列化浮點類型數字

4 序列化枚舉類型

5 序列化單字符

6 序列化Null

7 序列化Boolean

8 序列化16進制字節數組

9 序列化byte字節數組

10 序列化字符串

11 序列化字符數組

12 序列化列表字符串

13 序列化包含特殊字符字符串

14 序列化字段名稱

15 序列化Boolean類型字段鍵值對

16 序列化Int類型字段鍵值對

二 JSON成員函數

概要

JSON成員函數

序列化回調接口

序列化回調接口實現分析

內部註冊的序列化

1 BooleanCodec序列化

2 CharacterCodec序列化

3 IntegerCodec序列化

4 LongCodec序列化

5 FloatCodec序列化

6 BigDecimalCodec序列化

7 BigIntegerCodec序列化

8 StringCodec序列化

9 PrimitiveArraySerializer序列化

10 ObjectArrayCodec序列化

11 MiscCodec序列化

12 AppendableSerializer序列化

13 ToStringSerializer序列化

14 AtomicCodec序列化

15 ReferenceCodec序列化

16 CollectionCodec序列化

 特定序列化實現解析

 1 MapSerializer序列化

2 ListSerializer序列化

3 DateCodec序列化

4 JavaBeanSerializer序列化

反序列化

反序列化回調接口實現分析

內部註冊的反序列化

1 BooleanCodec反序列化

2 CharacterCodec反序列化

3 IntegerCodec反序列化

4 LongCodec反序列化

5 FloatCodec反序列化

6  BigDecimalCodec反序列化

 7 StringCodec反序列化

8 ObjectArrayCodec反序列化

9 JavaBeanDeserializer反序列化


序列化

fastjson核心功能包括序列化和反序列化,序列化的含義是將java對象轉換成跨語言的json字符串。我認爲從這裏作爲分析入口相對比較簡單,

SerializeWriter成員變量

com.alibaba.fastjson.serializer.SerializeWriter類非常重要,序列化輸出都是通過轉換底層操作,重要字段如下:

    /** 字符類型buffer */
    private final static ThreadLocal<char[]> bufLocal      = new ThreadLocal<char[]>();
    /** 字節類型buffer */
    private final static ThreadLocal<byte[]> bytesBufLocal = new ThreadLocal<byte[]>();

    /** 存儲序列化結果buffer */
    protected char                           buf[];

    /** buffer中包含的字符數 */
    protected int                            count;

    /** 序列化的特性,比如寫枚舉按照名字還是枚舉值 */
    protected int                            features;

    /** 序列化輸出器 */
    private final Writer                     writer;

    /** 是否使用單引號輸出json */
    protected boolean                        useSingleQuotes;
    /** 輸出字段是否追加 "和:字符 */
    protected boolean                        quoteFieldNames;
    /** 是否對字段排序 */
    protected boolean                        sortField;
    /** 禁用字段循環引用探測 */
    protected boolean                        disableCircularReferenceDetect;
    protected boolean                        beanToArray;
    /** 按照toString方式獲取對象字面值 */
    protected boolean                        writeNonStringValueAsString;
    /** 如果字段默認值不輸出,比如原型int,默認值0不輸出 */
    protected boolean                        notWriteDefaultValue;
    /** 序列化枚舉時使用枚舉name */
    protected boolean                        writeEnumUsingName;
    /** 序列化枚舉時使用枚舉toString值 */
    protected boolean                        writeEnumUsingToString;
    protected boolean                        writeDirect;
    /** key分隔符,默認單引號是',雙引號是" */
    protected char                           keySeperator;

    protected int                            maxBufSize = -1;

    protected boolean                        browserSecure;
    protected long                           sepcialBits;

一 SerializeWriter成員函數

1 序列化整形數字

    public void writeInt(int i) {
        /** 如果是整數最小值,調用字符串函數輸出到緩衝區*/
        if (i == Integer.MIN_VALUE) {
            write("-2147483648");
            return;
        }

        /** 根據數字判斷佔用的位數,負數會多一位用於存儲字符`-` */
        int size = (i < 0) ? IOUtils.stringSize(-i) + 1 : IOUtils.stringSize(i);

        int newcount = count + size;
        /** 如果當前存儲空間不夠 */
        if (newcount > buf.length) {
            if (writer == null) {
                /** 擴容到爲原有buf容量1.5倍+1, copy原有buf的字符*/
                expandCapacity(newcount);
            } else {
                char[] chars = new char[size];
                /** 將整數i轉換成單字符並存儲到chars數組 */
                IOUtils.getChars(i, size, chars);
                /** 將chars字符數組內容寫到buffer中*/
                write(chars, 0, chars.length);
                return;
            }
        }

        /** 如果buffer空間夠,直接將字符寫到buffer中 */
        IOUtils.getChars(i, newcount, buf);
        /** 重新計數buffer中字符數 */
        count = newcount;
    }

其中值得提一下的是IOUtils.getChars,裏面利用了Integer.getChars(int i, int index, char[] buf),主要的思想是整數超過65536 進行除以100, 循環取出數字後兩位,依次將個位和十位轉換爲單字符,如果整數小於等於65536,進行除以10,取出個位數字並轉換單字符,getCharts中 q = (i * 52429) >>> (16+3),可以理解爲 (i乘以0.1), 但是精度更高。


2 序列化長整形數字

    public void writeLong(long i) {
        boolean needQuotationMark = isEnabled(SerializerFeature.BrowserCompatible) //
                                    && (!isEnabled(SerializerFeature.WriteClassName)) //
                                    && (i > 9007199254740991L || i < -9007199254740991L);

        if (i == Long.MIN_VALUE) {
            if (needQuotationMark) write("\"-9223372036854775808\"");
            /** 如果是長整數最小值,調用字符串函數輸出到緩衝區*/
            else write("-9223372036854775808");
            return;
        }

        /** 根據數字判斷佔用的位數,負數會多一位用於存儲字符`-` */
        int size = (i < 0) ? IOUtils.stringSize(-i) + 1 : IOUtils.stringSize(i);

        int newcount = count + size;
        if (needQuotationMark) newcount += 2;
        /** 如果當前存儲空間不夠 */
        if (newcount > buf.length) {
            if (writer == null) {
                /** 擴容到爲原有buf容量1.5倍+1, copy原有buf的字符*/
                expandCapacity(newcount);
            } else {
                char[] chars = new char[size];
                /** 將長整數i轉換成單字符並存儲到chars數組 */
                IOUtils.getChars(i, size, chars);
                if (needQuotationMark) {
                    write('"');
                    write(chars, 0, chars.length);
                    write('"');
                } else {
                    write(chars, 0, chars.length);
                }
                return;
            }
        }

        /** 添加引號 */
        if (needQuotationMark) {
            buf[count] = '"';
            IOUtils.getChars(i, newcount - 1, buf);
            buf[newcount - 1] = '"';
        } else {
            IOUtils.getChars(i, newcount, buf);
        }

        count = newcount;
    }

序列化長整型和整型非常類似,增加了雙引號判斷,採用用了和Integer轉換爲單字符同樣的技巧。

 

3 序列化浮點類型數字

    public void writeDouble(double doubleValue, boolean checkWriteClassName) {
        /** 如果doubleValue不合法或者是無窮數,調用writeNull */
        if (Double.isNaN(doubleValue)
                || Double.isInfinite(doubleValue)) {
            writeNull();
        } else {
            /** 將高精度double轉換爲字符串 */
            String doubleText = Double.toString(doubleValue);
            /** 啓動WriteNullNumberAsZero特性,會將結尾.0去除 */
            if (isEnabled(SerializerFeature.WriteNullNumberAsZero) && doubleText.endsWith(".0")) {
                doubleText = doubleText.substring(0, doubleText.length() - 2);
            }

            /** 調用字符串輸出方法 */
            write(doubleText);

            /** 如果開啓序列化WriteClassName特性,輸出Double類型 */
            if (checkWriteClassName && isEnabled(SerializerFeature.WriteClassName)) {
                write('D');
            }
        }
    }

     public void writeFloat(float value, boolean checkWriteClassName) {
        /** 如果value不合法或者是無窮數,調用writeNull */
        if (Float.isNaN(value) //
                || Float.isInfinite(value)) {
            writeNull();
        } else {
            /** 將高精度float轉換爲字符串 */
            String floatText= Float.toString(value);
            /** 啓動WriteNullNumberAsZero特性,會將結尾.0去除 */
            if (isEnabled(SerializerFeature.WriteNullNumberAsZero) && floatText.endsWith(".0")) {
                floatText = floatText.substring(0, floatText.length() - 2);
            }
            write(floatText);

            /** 如果開啓序列化WriteClassName特性,輸出float類型 */
            if (checkWriteClassName && isEnabled(SerializerFeature.WriteClassName)) {
                write('F');
            }
        }
    }

序列化浮點類型的基本思路是先轉換爲字符串,然後在輸出到輸出流中。

 

4 序列化枚舉類型

    public void writeEnum(Enum<?> value) {
        if (value == null) {
            /** 如果枚舉value爲空,調用writeNull輸出 */
            writeNull();
            return;
        }

        String strVal = null;
        /** 如果開啓序列化輸出枚舉名字作爲屬性值 */
        if (writeEnumUsingName && !writeEnumUsingToString) {
            strVal = value.name();
        } else if (writeEnumUsingToString) {
            /** 採用枚舉默認toString方法作爲屬性值 */
            strVal = value.toString();;
        }

        if (strVal != null) {
            /** 如果開啓引號特性,輸出json包含引號的字符串 */
            char quote = isEnabled(SerializerFeature.UseSingleQuotes) ? '\'' : '"';
            write(quote);
            write(strVal);
            write(quote);
        } else {
            /** 輸出枚舉所在的索引號 */
            writeInt(value.ordinal());
        }
    }

5 序列化單字符

    public void write(int c) {
        int newcount = count + 1;
        /** 如果當前存儲空間不夠 */
        if (newcount > buf.length) {
            if (writer == null) {
                expandCapacity(newcount);
            } else {
                /** 強制流輸出並刷新緩衝區 */
                flush();
                newcount = 1;
            }
        }
        /** 存儲單字符到buffer並更新計數 */
        buf[count] = (char) c;
        count = newcount;
    }

6 序列化Null

    public void writeNull() {
        /** 調用輸出字符串null */
        write("null");
    }

7 序列化Boolean

    public void write(boolean value) {
        if (value) {
            /** 輸出true字符串 */
            write("true");
        } else {
            /** 輸出false字符串 */
            write("false");
        }
    }

8 序列化16進制字節數組

    public void writeHex(byte[] bytes) {
        /** 計算總共字符長度, 乘以2 代表一個字符要佔用2字節, 3代表要添加 x 和 前後添加' */
        int newcount = count + bytes.length * 2 + 3;
        if (newcount > buf.length) {
            if (writer != null) {
                char[] chars = new char[bytes.length + 3];
                int pos = 0;
                chars[pos++] = 'x';
                chars[pos++] = '\'';

                for (int i = 0; i < bytes.length; ++i) {
                    byte b = bytes[i];

                    int a = b & 0xFF;
                    /** 取字節的高四位 1111 0000*/
                    int b0 = a >> 4;
                    /** 取字節的低四位 0000 1111*/
                    int b1 = a & 0xf;

                    /** 索引低索引存儲字節高位
                     *  如果4位表示的數字是 0~9, 轉換爲ascii的 0~9
                     *  如果4位表示的不是數字, 轉換爲16進制ascii碼字符
                     */
                    chars[pos++] = (char) (b0 + (b0 < 10 ? 48 : 55));
                    chars[pos++] = (char) (b1 + (b1 < 10 ? 48 : 55));
                }
                chars[pos++] = '\'';
                try {
                    writer.write(chars);
                } catch (IOException ex) {
                    throw new JSONException("writeBytes error.", ex);
                }
                return;
            }
            /** buffer容量不夠並且輸出器爲空,觸發擴容 */
            expandCapacity(newcount);
        }

        buf[count++] = 'x';
        buf[count++] = '\'';

        for (int i = 0; i < bytes.length; ++i) {
            byte b = bytes[i];

            int a = b & 0xFF;
            /** 取字節的高四位 */
            int b0 = a >> 4;
            /** 取字節的低四位 */
            int b1 = a & 0xf;

            /** 索引低索引存儲字節高位
             *  如果4位表示的數字是 0~9, 轉換爲ascii的 0~9
             *  如果4位表示的不是數字, 轉換爲16進制ascii碼字符
             */
            buf[count++] = (char) (b0 + (b0 < 10 ? 48 : 55));
            buf[count++] = (char) (b1 + (b1 < 10 ? 48 : 55));
        }
        buf[count++] = '\'';
    }

writeHex 這個序列化方法主要對16進制的自己轉換爲佔用2個ascii碼字符,添加單引號和x前綴。

9 序列化byte字節數組

   public void writeByteArray(byte[] bytes) {
        if (isEnabled(SerializerFeature.WriteClassName.mask)) {
            /** 如果開啓序列化特性WriteClassName,直接寫16進制字符 */
            writeHex(bytes);
            return;
        }

        int bytesLen = bytes.length;
        final char quote = useSingleQuotes ? '\'' : '"';
        if (bytesLen == 0) {
            String emptyString = useSingleQuotes ? "''" : "\"\"";
            /** 如果字節數組長度爲0,輸出空白字符 */
            write(emptyString);
            return;
        }

        final char[] CA = IOUtils.CA;

        /** 驗證長度是24bit位整數倍 */
        int eLen = (bytesLen / 3) * 3;
        /** base64 編碼字符長度
         *
         *  base64 :
         *  第一步,將每三個字節作爲一組,一共是24個二進制位。
         *  第二步,將這24個二進制位分爲四組,每個組有6個二進制位。
         *  第三步,在每組前面加兩個00,擴展成32個二進制位,即四個字節。
         *  第四步,根據下表,得到擴展後的每個字節的對應符號,這就是Base64的編碼值。
         *
         *  ref: http://www.ruanyifeng.com/blog/2008/06/base64.html
         */
        int charsLen = ((bytesLen - 1) / 3 + 1) << 2;
        // char[] chars = new char[charsLen];
        int offset = count;
        int newcount = count + charsLen + 2;
        if (newcount > buf.length) {
            if (writer != null) {
                write(quote);

                for (int s = 0; s < eLen;) {
                    /** 三個字節爲一組, 擴展爲四個字節 */
                    int i = (bytes[s++] & 0xff) << 16 | (bytes[s++] & 0xff) << 8 | (bytes[s++] & 0xff);

                    write(CA[(i >>> 18) & 0x3f]);
                    write(CA[(i >>> 12) & 0x3f]);
                    write(CA[(i >>> 6) & 0x3f]);
                    /** 填充00 */
                    write(CA[i & 0x3f]);
                }

                /** 對齊並編碼剩餘不足3個字節爲一組的數據 */
                // Pad and encode last bits if source isn't even 24 bits.
                int left = bytesLen - eLen; // 0 - 2.
                if (left > 0) {

                    /**
                     * a) 1個字節的情況:
                     * 將這1字節8位二進制,每6位分成2組,最後一組除了前面加00,後面加上0000,
                     * 這樣得到 兩位的Base64編碼, 在末尾補上2個"="號
                     *
                     * b) 2個字節的情況:
                     * 將這2字節的一共16個二進制位,每6位分成3組,最後一組除了前面加00,後面也要加00,
                     * 這樣得到 3位的Base64編碼, 在末尾補上"="號
                     *
                     *
                     * 如果只有1個字節,按照前面規則a)
                     * 第1組是6位,第2組後面4個0, 因此應該左移 10 = 6 + 4
                     *
                     * 如果只有2個字節,按照前面規則b)
                     * 第1個字節左移 10 位 加上 第2個字節左移 2 位補0即可
                     */
                    int i = ((bytes[eLen] & 0xff) << 10) | (left == 2 ? ((bytes[bytesLen - 1] & 0xff) << 2) : 0);

                    /** 擴展爲四個字節 */
                    write(CA[i >> 12]);
                    write(CA[(i >>> 6) & 0x3f]);
                    write(left == 2 ? CA[i & 0x3f] : '=');
                    write('=');
                }

                write(quote);
                return;
            }
            expandCapacity(newcount);
        }
        count = newcount;
        buf[offset++] = quote;

        // Encode even 24-bits
        for (int s = 0, d = offset; s < eLen;) {
            /** 三個字節爲一組, 擴展爲四個字節 */
            int i = (bytes[s++] & 0xff) << 16 | (bytes[s++] & 0xff) << 8 | (bytes[s++] & 0xff);

            // Encode the int into four chars
            buf[d++] = CA[(i >>> 18) & 0x3f];
            buf[d++] = CA[(i >>> 12) & 0x3f];
            buf[d++] = CA[(i >>> 6) & 0x3f];
            /** 填充00 */
            buf[d++] = CA[i & 0x3f];
        }

        /** 對齊並編碼剩餘不足3個字節爲一組的數據 */
        int left = bytesLen - eLen; // 0 - 2.
        if (left > 0) {
            // Prepare the int
            int i = ((bytes[eLen] & 0xff) << 10) | (left == 2 ? ((bytes[bytesLen - 1] & 0xff) << 2) : 0);

            /** 擴展爲四個字節 */
            buf[newcount - 5] = CA[i >> 12];
            buf[newcount - 4] = CA[(i >>> 6) & 0x3f];
            buf[newcount - 3] = left == 2 ? CA[i & 0x3f] : '=';
            buf[newcount - 2] = '=';
        }
        buf[newcount - 1] = quote;
    }

writeByteArray序列化字節數組實際上就是做了base64編碼轉換,代碼添加了詳盡的註釋幫助理解。

10 序列化字符串

    public void write(String str, int off, int len) {
        /** 計算總共字符串長度 */
        int newcount = count + len;
        /** 如果當前存儲空間不夠 */
        if (newcount > buf.length) {
            if (writer == null) {
                expandCapacity(newcount);
            } else {
                /**
                 * 如果字符串str超過緩衝區大小, 進行循環拷貝
                 */
                do {
                    /** 計算當前buffer剩餘容納字符數 */
                    int rest = buf.length - count;
                    /** 將字符串str[off, off + rest) 拷貝到buf[count, ...]中*/
                    str.getChars(off, off + rest, buf, count);
                    count = buf.length;
                    /** 強制刷新輸出流,會重置count = 0 */
                    flush();
                    /** 計算剩餘需要拷貝的字符數量 */
                    len -= rest;
                    /** 剩餘要拷貝字符在str中偏移量(索引) */
                    off += rest;
                } while (len > buf.length);
                newcount = len;
            }
        }
        /** 存儲空間充足,直接將str[off, off + len) 拷貝到buf[count, ...]中*/
        str.getChars(off, off + len, buf, count);
        count = newcount;
    }

序列化字符串write(string),最終都會轉化爲上面形式write(string, 0, string.length)

11 序列化字符數組

    public void write(char c[], int off, int len) {
        if (off < 0 //
            || off > c.length //
            || len < 0 //
            || off + len > c.length //
            || off + len < 0) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return;
        }

        /** 計算總共字符串長度 */
        int newcount = count + len;
        /** 如果當前存儲空間不夠 */
        if (newcount > buf.length) {
            if (writer == null) {
                expandCapacity(newcount);
            } else {
                /**
                 * 如果字符數組c超過緩衝區大小, 進行循環拷貝
                 */
                do {
                    /** 計算當前buffer剩餘容納字符數 */
                    int rest = buf.length - count;
                    /** c[off, off + rest) 拷貝到buf[count, ...]中*/
                    System.arraycopy(c, off, buf, count, rest);
                    count = buf.length;
                    /** 強制刷新輸出流,會重置count = 0 */
                    flush();
                    /** 計算剩餘需要拷貝的字符數量 */
                    len -= rest;
                    /** 剩餘要拷貝字符在c中偏移量(索引) */
                    off += rest;
                } while (len > buf.length);
                newcount = len;
            }
        }
        System.arraycopy(c, off, buf, count, len);
        count = newcount;
    }

12 序列化列表字符串

    public void write(char c[], int off, int len) {
        if (off < 0 //
            || off > c.length //
            || len < 0 //
            || off + len > c.length //
            || off + len < 0) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return;
        }

        /** 計算總共字符串長度 */
        int newcount = count + len;
        /** 如果當前存儲空間不夠 */
        if (newcount > buf.length) {
            if (writer == null) {
                expandCapacity(newcount);
            } else {
                /**
                 * 如果字符數組c超過緩衝區大小, 進行循環拷貝
                 */
                do {
                    /** 計算當前buffer剩餘容納字符數 */
                    int rest = buf.length - count;
                    /** c[off, off + rest) 拷貝到buf[count, ...]中*/
                    System.arraycopy(c, off, buf, count, rest);
                    count = buf.length;
                    /** 強制刷新輸出流,會重置count = 0 */
                    flush();
                    /** 計算剩餘需要拷貝的字符數量 */
                    len -= rest;
                    /** 剩餘要拷貝字符在c中偏移量(索引) */
                    off += rest;
                } while (len > buf.length);
                newcount = len;
            }
        }
        System.arraycopy(c, off, buf, count, len);
        count = newcount;
    }

序列化字符串會轉化成[“element”, "element", ...]格式。如果列表字符串中包含特殊字符,調用特化版本writeStringWithDoubleQuote(text, (char) 0)

13 序列化包含特殊字符字符串

    public void write(char c[], int off, int len) {
        if (off < 0 //
            || off > c.length //
            || len < 0 //
            || off + len > c.length //
            || off + len < 0) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return;
        }

        /** 計算總共字符串長度 */
        int newcount = count + len;
        /** 如果當前存儲空間不夠 */
        if (newcount > buf.length) {
            if (writer == null) {
                expandCapacity(newcount);
            } else {
                /**
                 * 如果字符數組c超過緩衝區大小, 進行循環拷貝
                 */
                do {
                    /** 計算當前buffer剩餘容納字符數 */
                    int rest = buf.length - count;
                    /** c[off, off + rest) 拷貝到buf[count, ...]中*/
                    System.arraycopy(c, off, buf, count, rest);
                    count = buf.length;
                    /** 強制刷新輸出流,會重置count = 0 */
                    flush();
                    /** 計算剩餘需要拷貝的字符數量 */
                    len -= rest;
                    /** 剩餘要拷貝字符在c中偏移量(索引) */
                    off += rest;
                } while (len > buf.length);
                newcount = len;
            }
        }
        System.arraycopy(c, off, buf, count, len);
        count = newcount;
    }

writeStringWithDoubleQuote方法實現實在是太長了,這個方法主要做了以下幾件事情:

1  如果開啓序列化BrowserCompatible特性,執行ascii轉換成native編碼,節省空間。
2   如果輸出器writer不爲空,會自動觸發buffer擴容(原有容量1.5倍+1)。
另外一個針對特殊字符的字符串序列化方法writeStringWithDoubleQuote(char[] text, final char seperator),因爲和writeStringWithDoubleQuote(String text, final char seperator)版本極其類似,所以不再冗餘分析。

序列化字符串的方法包括添加單引號的版本,詳細請參考 writeStringWithSingleQuote :

    public void write(char c[], int off, int len) {
        if (off < 0 //
            || off > c.length //
            || len < 0 //
            || off + len > c.length //
            || off + len < 0) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return;
        }

        /** 計算總共字符串長度 */
        int newcount = count + len;
        /** 如果當前存儲空間不夠 */
        if (newcount > buf.length) {
            if (writer == null) {
                expandCapacity(newcount);
            } else {
                /**
                 * 如果字符數組c超過緩衝區大小, 進行循環拷貝
                 */
                do {
                    /** 計算當前buffer剩餘容納字符數 */
                    int rest = buf.length - count;
                    /** c[off, off + rest) 拷貝到buf[count, ...]中*/
                    System.arraycopy(c, off, buf, count, rest);
                    count = buf.length;
                    /** 強制刷新輸出流,會重置count = 0 */
                    flush();
                    /** 計算剩餘需要拷貝的字符數量 */
                    len -= rest;
                    /** 剩餘要拷貝字符在c中偏移量(索引) */
                    off += rest;
                } while (len > buf.length);
                newcount = len;
            }
        }
        System.arraycopy(c, off, buf, count, len);
        count = newcount;
    }

writeStringWithSingleQuote這個方法主要做了以下幾件事情:

1  針對特殊字符,添加轉譯字符並且替換特殊字符爲普通字符
2   如果輸出器writer不爲空,會自動觸發buffer擴容(原有容量1.5倍+1)。

  另外一個針對特殊字符的字符串序列化方法writeStringWithSingleQuote(char[]),因爲和writeStringWithSingleQuote(String)版本極其類似,所以不再冗餘分析。

14 序列化字段名稱

    public void writeFieldName(String key, boolean checkSpecial) {
        if (key == null) {
            /** 如果字段key爲null, 輸出 "null:" */
            write("null:");
            return;
        }

        if (useSingleQuotes) {
            if (quoteFieldNames) {
                /** 使用單引號並且在字段後面加':'輸出 標準的json key*/
                writeStringWithSingleQuote(key);
                write(':');
            } else {
                /** 輸出key,如果有特殊字符會自動添加單引號 */
                writeKeyWithSingleQuoteIfHasSpecial(key);
            }
        } else {
            if (quoteFieldNames) {
                /** 使用雙引號輸出json key 並添加 : */
                writeStringWithDoubleQuote(key, ':');
            } else {
                boolean hashSpecial = key.length() == 0;
                for (int i = 0; i < key.length(); ++i) {
                    char ch = key.charAt(i);
                    boolean special = (ch < 64 && (sepcialBits & (1L << ch)) != 0) || ch == '\\';
                    if (special) {
                        hashSpecial = true;
                        break;
                    }
                }
                if (hashSpecial) {
                    /** 如果包含特殊字符,會進行特殊字符轉換輸出,eg: 使用轉換後的native編碼輸出 */
                    writeStringWithDoubleQuote(key, ':');
                } else {
                    /** 輸出字段不加引號 */
                    write(key);
                    write(':');
                }
            }
        }
    }

序列化字段名稱方法writeFieldName主要的任務:

1  完成字段特殊字符的轉譯
2   添加字段的引號


處理輸出key的特殊字符方法writeStringWithDoubleQuote前面已經分析過了,序列化字段名稱是否需要添加引號和特殊字符處理參考writeKeyWithSingleQuoteIfHasSpecial:

    private void writeKeyWithSingleQuoteIfHasSpecial(String text) {
        final byte[] specicalFlags_singleQuotes = IOUtils.specicalFlags_singleQuotes;

        int len = text.length();
        int newcount = count + len + 1;
        if (newcount > buf.length) {
            if (writer != null) {
                if (len == 0) {
                    /** 如果字段爲null, 輸出空白字符('':)作爲key */
                    write('\'');
                    write('\'');
                    write(':');
                    return;
                }

                boolean hasSpecial = false;
                for (int i = 0; i < len; ++i) {
                    char ch = text.charAt(i);
                    if (ch < specicalFlags_singleQuotes.length && specicalFlags_singleQuotes[ch] != 0) {
                        hasSpecial = true;
                        break;
                    }
                }

                /** 如果有特殊字符,給字段key添加單引號 */
                if (hasSpecial) {
                    write('\'');
                }
                for (int i = 0; i < len; ++i) {
                    char ch = text.charAt(i);
                    if (ch < specicalFlags_singleQuotes.length && specicalFlags_singleQuotes[ch] != 0) {
                        /** 如果輸出key中包含特殊字符,添加轉譯字符並將特殊字符替換成普通字符 */
                        write('\\');
                        write(replaceChars[(int) ch]);
                    } else {
                        write(ch);
                    }
                }

                /** 如果有特殊字符,給字段key添加單引號 */
                if (hasSpecial) {
                    write('\'');
                }
                write(':');
                return;
            }
            /** 輸出器writer爲null觸發擴容,擴容到爲原有buf容量1.5倍+1, copy原有buf的字符*/
            expandCapacity(newcount);
        }

        if (len == 0) {
            int newCount = count + 3;
            if (newCount > buf.length) {
                expandCapacity(count + 3);
            }
            buf[count++] = '\'';
            buf[count++] = '\'';
            buf[count++] = ':';
            return;
        }

        int start = count;
        int end = start + len;

        /** buffer能夠容納字符串,直接拷貝text到buf緩衝數組 */
        text.getChars(0, len, buf, start);
        count = newcount;

        boolean hasSpecial = false;

        for (int i = start; i < end; ++i) {
            char ch = buf[i];
            if (ch < specicalFlags_singleQuotes.length && specicalFlags_singleQuotes[ch] != 0) {
                if (!hasSpecial) {
                    newcount += 3;
                    if (newcount > buf.length) {
                        expandCapacity(newcount);
                    }
                    count = newcount;

                    /** 將字符後移兩位,插入字符'\ 並替換特殊字符爲普通字符 */
                    System.arraycopy(buf, i + 1, buf, i + 3, end - i - 1);
                    /** 將字符後移一位 */
                    System.arraycopy(buf, 0, buf, 1, i);
                    buf[start] = '\'';
                    buf[++i] = '\\';
                    buf[++i] = replaceChars[(int) ch];
                    end += 2;
                    buf[count - 2] = '\'';

                    hasSpecial = true;
                } else {
                    newcount++;
                    if (newcount > buf.length) {
                        expandCapacity(newcount);
                    }
                    count = newcount;

                    /** 包含特殊字符,將字符後移一位,插入轉譯字符\ 並替換特殊字符爲普通字符 */
                    System.arraycopy(buf, i + 1, buf, i + 2, end - i);
                    buf[i] = '\\';
                    buf[++i] = replaceChars[(int) ch];
                    end++;
                }
            }
        }

        buf[newcount - 1] = ':';
    }

15 序列化Boolean類型字段鍵值對

    public void writeFieldValue(char seperator, String name, boolean value) {
        if (!quoteFieldNames) {
            /** 如果不需要輸出雙引號,則一次輸出字段分隔符,字段名字,字段值 */
            write(seperator);
            writeFieldName(name);
            write(value);
            return;
        }
        /** true 佔用4位, false 佔用5位 */
        int intSize = value ? 4 : 5;

        int nameLen = name.length();
        /** 輸出總長度, 中間的4  代表 key 和 value 總共佔用4個引號 */
        int newcount = count + nameLen + 4 + intSize;
        if (newcount > buf.length) {
            if (writer != null) {
                /** 依次輸出字段分隔符,字段:字段值 */
                write(seperator);
                writeString(name);
                write(':');
                write(value);
                return;
            }
            /** 輸出器writer爲null觸發擴容,擴容到爲原有buf容量1.5倍+1, copy原有buf的字符*/
            expandCapacity(newcount);
        }

        int start = count;
        count = newcount;

        /** 輸出字段分隔符,一般是, */
        buf[start] = seperator;

        int nameEnd = start + nameLen + 1;

        /** 輸出字段屬性分隔符,一般是單引號或雙引號 */
        buf[start + 1] = keySeperator;

        /** 輸出字段名稱 */
        name.getChars(0, nameLen, buf, start + 2);

        /** 字段名稱添加分隔符,一般是單引號或雙引號 */
        buf[nameEnd + 1] = keySeperator;

        /** 輸出boolean類型字符串值 */
        if (value) {
            System.arraycopy(":true".toCharArray(), 0, buf, nameEnd + 2, 5);
        } else {
            System.arraycopy(":false".toCharArray(), 0, buf, nameEnd + 2, 6);
        }
    }

序列化boolean類型的鍵值對屬性,因爲不涉及特殊字符,主要就是把原型序列化爲字面量值。

16 序列化Int類型字段鍵值對

    public void writeFieldValue(char seperator, String name, int value) {
        if (value == Integer.MIN_VALUE || !quoteFieldNames) {
            /** 如果是整數最小值或不需要輸出雙引號,則一次輸出字段分隔符,字段名字,字段值 */
            write(seperator);
            writeFieldName(name);
            writeInt(value);
            return;
        }

        /** 根據數字判斷佔用的位數,負數會多一位用於存儲字符`-` */
        int intSize = (value < 0) ? IOUtils.stringSize(-value) + 1 : IOUtils.stringSize(value);

        int nameLen = name.length();
        int newcount = count + nameLen + 4 + intSize;
        if (newcount > buf.length) {
            if (writer != null) {
                write(seperator);
                writeFieldName(name);
                writeInt(value);
                return;
            }
            /** 擴容到爲原有buf容量1.5倍+1, copy原有buf的字符*/
            expandCapacity(newcount);
        }

        int start = count;
        count = newcount;

        /** 輸出字段分隔符,一般是, */
        buf[start] = seperator;

        int nameEnd = start + nameLen + 1;

        /** 輸出字段屬性分隔符,一般是單引號或雙引號 */
        buf[start + 1] = keySeperator;

        /** 輸出字段名稱 */
        name.getChars(0, nameLen, buf, start + 2);

        buf[nameEnd + 1] = keySeperator;
        buf[nameEnd + 2] = ':';

        /** 輸出整數值,對整數轉化成單字符 */
        IOUtils.getChars(value, count, buf);
    }

序列化int類型的鍵值對屬性,因爲不涉及特殊字符,主要就是把原型序列化爲字面量值。截止到現在,已經把核心SerializWriter類講完了,剩餘字段鍵值對極其類似writeFieldValue boolean和int等,因此無需冗餘分析。因爲序列化真正開始之前,這個類極其基礎並且非常重要,因此花的時間較多。
 

二 JSON成員函數

概要

fastjson序列化主要使用入口就是在JSON.java類中,它提供非常簡便和友好的api將java對象轉換成json字符串。

JSON成員函數

    /**
     *  便捷序列化java對象,序列化對象可以包含任意泛型屬性字段,但是不適用本身是泛型的對象。
     *  默認序列化返回字符串,可以使用writeJSONString(Writer, Object, SerializerFeature[])
     *  將序列化字符串輸出到指定輸出器中
     */
    public static String toJSONString(Object object) {
        /**
         * 直接調用重載方法,將指定object序列化成json字符串,忽略序列化filter
         */
        return toJSONString(object, emptyFilters);
    }

使用便捷接口toJSONString方法,可以將任意java對象序列化爲json字符串,內部調用toJSONString(Object, SerializeFilter[], SerializerFeature... ) :

    public static String toJSONString(Object object, SerializeFilter[] filters, SerializerFeature... features) {
        return toJSONString(object, SerializeConfig.globalInstance, filters, null, DEFAULT_GENERATE_FEATURE, features);
    }

繼續跟蹤方法調用到toJSONString(Object, SerializeConfig ,SerializeFilter[], String, int, SerializerFeature... ) :

    public static String toJSONString(Object object,                   /** 序列化對象    */
                                      SerializeConfig config,          /** 全局序列化配置 */
                                      SerializeFilter[] filters,       /** 序列化攔截器   */
                                      String dateFormat,               /** 序列化日期格式 */
                                      int defaultFeatures,             /** 默認序列化特性 */
                                      SerializerFeature... features) { /** 自定義序列化特性 */
        /** 初始化序列化writer,用features覆蓋defaultFeatures配置 */
        SerializeWriter out = new SerializeWriter(null, defaultFeatures, features);

        try {

            /**
             *  初始化JSONSerializer,序列化類型由它委託config查找具體
             *  序列化處理器處理,序列化結果寫入out的buffer中
             */
            JSONSerializer serializer = new JSONSerializer(out, config);

            if (dateFormat != null && dateFormat.length() != 0) {
                serializer.setDateFormat(dateFormat);
                /** 調用out 重新配置屬性 並且打開WriteDateUseDateFormat特性 */
                serializer.config(SerializerFeature.WriteDateUseDateFormat, true);
            }

            if (filters != null) {
                for (SerializeFilter filter : filters) {
                    /** 添加攔截器 */
                    serializer.addFilter(filter);
                }
            }

            /** 使用序列化實例轉換對象,查找具體序列化實例委託給config查找 */
            serializer.write(object);

            return out.toString();
        } finally {
            out.close();
        }
    }

這個序列化方法實際並不是真正執行序列化操作,首先做序列化特性配置,然後追加序列化攔截器,開始執行序列化對象操作委託給了config對象查找。

我們繼續進入serializer.write(object) 查看:

    public final void write(Object object) {
        if (object == null) {
            /** 如果對象爲空,直接輸出 "null" 字符串 */
            out.writeNull();
            return;
        }

        Class<?> clazz = object.getClass();
        /** 根據對象的Class類型查找具體序列化實例 */
        ObjectSerializer writer = getObjectWriter(clazz);

        try {
            /** 使用具體serializer實例處理對象 */
            writer.write(this, object, null, null, 0);
        } catch (IOException e) {
            throw new JSONException(e.getMessage(), e);
        }
    }

 

序列化回調接口

ObjectSerializer序列化接口

我們發現真正序列化對象的時候是由具體ObjectSerializer實例完成,我們首先查看一下接口定義:

    void write(JSONSerializer serializer, /** json序列化實例 */
               Object object,       /** 待序列化的對象*/
               Object fieldName,    /** 待序列化字段*/
               Type fieldType,      /** 待序列化字段類型 */
               int features) throws IOException;

當fastjson序列化特定的字段時會回調這個方法。

我們繼續跟蹤writer.write(this, object, null, null, 0) :

    public final void write(Object object) {
        if (object == null) {
            /** 如果對象爲空,直接輸出 "null" 字符串 */
            out.writeNull();
            return;
        }

        Class<?> clazz = object.getClass();
        /** 根據對象的Class類型查找具體序列化實例 */
        ObjectSerializer writer = getObjectWriter(clazz);

        try {
            /** 使用具體serializer實例處理對象 */
            writer.write(this, object, null, null, 0);
        } catch (IOException e) {
            throw new JSONException(e.getMessage(), e);
        }
    }

我們發現在方法內部調用getObjectWriter(clazz)根據具體類型查找序列化實例,方法內部只有一行調用 config.getObjectWriter(clazz),讓我們更進一步查看委託實現細節com.alibaba.fastjson.serializer.SerializeConfig#getObjectWriter(java.lang.Class<?>):
 

    public ObjectSerializer getObjectWriter(Class<?> clazz) {
        return getObjectWriter(clazz, true);
    }

內部又調用com.alibaba.fastjson.serializer.SerializeConfig#getObjectWriter(java.lang.Class<?>, boolean),這個類實現相對複雜了一些,我會按照代碼順序梳理所有序列化實例的要點 :

    private ObjectSerializer getObjectWriter(Class<?> clazz, boolean create) {
        /** 首先從內部已經註冊查找特定class的序列化實例 */
        ObjectSerializer writer = serializers.get(clazz);

        if (writer == null) {
            try {
                final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
                /** 使用當前線程類加載器 查找 META-INF/services/AutowiredObjectSerializer.class實現類 */
                for (Object o : ServiceLoader.load(AutowiredObjectSerializer.class, classLoader)) {
                    if (!(o instanceof AutowiredObjectSerializer)) {
                        continue;
                    }

                    AutowiredObjectSerializer autowired = (AutowiredObjectSerializer) o;
                    for (Type forType : autowired.getAutowiredFor()) {
                        /** 如果存在,註冊到內部serializers緩存中 */
                        put(forType, autowired);
                    }
                }
            } catch (ClassCastException ex) {
                // skip
            }

            /** 嘗試在已註冊緩存找到特定class的序列化實例 */
            writer = serializers.get(clazz);
        }

        if (writer == null) {
            /** 使用加載JSON類的加載器 查找 META-INF/services/AutowiredObjectSerializer.class實現類 */
            final ClassLoader classLoader = JSON.class.getClassLoader();
            if (classLoader != Thread.currentThread().getContextClassLoader()) {
                try {
                    for (Object o : ServiceLoader.load(AutowiredObjectSerializer.class, classLoader)) {

                        if (!(o instanceof AutowiredObjectSerializer)) {
                            continue;
                        }

                        AutowiredObjectSerializer autowired = (AutowiredObjectSerializer) o;
                        for (Type forType : autowired.getAutowiredFor()) {
                            /** 如果存在,註冊到內部serializers緩存中 */
                            put(forType, autowired);
                        }
                    }
                } catch (ClassCastException ex) {
                    // skip
                }

                /** 嘗試在已註冊緩存找到特定class的序列化實例 */
                writer = serializers.get(clazz);
            }
        }

        if (writer == null) {
            String className = clazz.getName();
            Class<?> superClass;

            if (Map.class.isAssignableFrom(clazz)) {
                /** 如果class實現類Map接口,使用MapSerializer序列化 */
                put(clazz, writer = MapSerializer.instance);
            } else if (List.class.isAssignableFrom(clazz)) {
                /** 如果class實現類List接口,使用ListSerializer序列化 */
                put(clazz, writer = ListSerializer.instance);
            } else if (Collection.class.isAssignableFrom(clazz)) {
                /** 如果class實現類Collection接口,使用CollectionCodec序列化 */
                put(clazz, writer = CollectionCodec.instance);
            } else if (Date.class.isAssignableFrom(clazz)) {
                /** 如果class繼承Date,使用DateCodec序列化 */
                put(clazz, writer = DateCodec.instance);
            } else if (JSONAware.class.isAssignableFrom(clazz)) {
                /** 如果class實現類JSONAware接口,使用JSONAwareSerializer序列化 */
                put(clazz, writer = JSONAwareSerializer.instance);
            } else if (JSONSerializable.class.isAssignableFrom(clazz)) {
                /** 如果class實現類JSONSerializable接口,使用JSONSerializableSerializer序列化 */
                put(clazz, writer = JSONSerializableSerializer.instance);
            } else if (JSONStreamAware.class.isAssignableFrom(clazz)) {
                /** 如果class實現類JSONStreamAware接口,使用MiscCodecr序列化 */
                put(clazz, writer = MiscCodec.instance);
            } else if (clazz.isEnum()) {
                JSONType jsonType = TypeUtils.getAnnotation(clazz, JSONType.class);
                if (jsonType != null && jsonType.serializeEnumAsJavaBean()) {
                    /** 如果是枚舉類型,並且啓用特性 serializeEnumAsJavaBean
                     *  使用JavaBeanSerializer序列化(假設沒有啓用asm)
                     */
                    put(clazz, writer = createJavaBeanSerializer(clazz));
                } else {
                    /** 如果是枚舉類型,沒有啓用特性 serializeEnumAsJavaBean
                     *  使用EnumSerializer序列化
                     */
                    put(clazz, writer = EnumSerializer.instance);
                }
            } else if ((superClass = clazz.getSuperclass()) != null && superClass.isEnum()) {
                JSONType jsonType = TypeUtils.getAnnotation(superClass, JSONType.class);
                if (jsonType != null && jsonType.serializeEnumAsJavaBean()) {
                    /** 如果父類是枚舉類型,並且啓用特性 serializeEnumAsJavaBean
                     *  使用JavaBeanSerializer序列化(假設沒有啓用asm)
                     */
                    put(clazz, writer = createJavaBeanSerializer(clazz));
                } else {
                    /** 如果父類是枚舉類型,沒有啓用特性 serializeEnumAsJavaBean
                     *  使用EnumSerializer序列化
                     */
                    put(clazz, writer = EnumSerializer.instance);
                }
            } else if (clazz.isArray()) {
                Class<?> componentType = clazz.getComponentType();
                /** 如果是數組類型,根據數組實際類型查找序列化實例 */
                ObjectSerializer compObjectSerializer = getObjectWriter(componentType);
                put(clazz, writer = new ArraySerializer(componentType, compObjectSerializer));
            } else if (Throwable.class.isAssignableFrom(clazz)) {
                /** 註冊通用JavaBeanSerializer序列化處理 Throwable */
                SerializeBeanInfo beanInfo = TypeUtils.buildBeanInfo(clazz, null, propertyNamingStrategy);
                beanInfo.features |= SerializerFeature.WriteClassName.mask;
                put(clazz, writer = new JavaBeanSerializer(beanInfo));
            } else if (TimeZone.class.isAssignableFrom(clazz) || Map.Entry.class.isAssignableFrom(clazz)) {
                /** 如果class實現Map.Entry接口或者繼承類TimeZone,使用MiscCodecr序列化 */
                put(clazz, writer = MiscCodec.instance);
            } else if (Appendable.class.isAssignableFrom(clazz)) {
                /** 如果class實現Appendable接口,使用AppendableSerializer序列化 */
                put(clazz, writer = AppendableSerializer.instance);
            } else if (Charset.class.isAssignableFrom(clazz)) {
                /** 如果class繼承Charset抽象類,使用ToStringSerializer序列化 */
                put(clazz, writer = ToStringSerializer.instance);
            } else if (Enumeration.class.isAssignableFrom(clazz)) {
                /** 如果class實現Enumeration接口,使用EnumerationSerializer序列化 */
                put(clazz, writer = EnumerationSerializer.instance);
            } else if (Calendar.class.isAssignableFrom(clazz)
                    || XMLGregorianCalendar.class.isAssignableFrom(clazz)) {
                /** 如果class繼承類Calendar或者XMLGregorianCalendar,使用CalendarCodec序列化 */
                put(clazz, writer = CalendarCodec.instance);
            } else if (Clob.class.isAssignableFrom(clazz)) {
                /** 如果class實現Clob接口,使用ClobSeriliazer序列化 */
                put(clazz, writer = ClobSeriliazer.instance);
            } else if (TypeUtils.isPath(clazz)) {
                /** 如果class實現java.nio.file.Path接口,使用ToStringSerializer序列化 */
                put(clazz, writer = ToStringSerializer.instance);
            } else if (Iterator.class.isAssignableFrom(clazz)) {
                /** 如果class實現Iterator接口,使用MiscCodec序列化 */
                put(clazz, writer = MiscCodec.instance);
            } else {
                /**
                 *  如果class的name是"java.awt."開頭 並且
                 *  繼承 Point、Rectangle、Font或者Color 其中之一
                 */
                if (className.startsWith("java.awt.")
                    && AwtCodec.support(clazz)
                ) {
                    // awt
                    if (!awtError) {
                        try {
                            String[] names = new String[]{
                                    "java.awt.Color",
                                    "java.awt.Font",
                                    "java.awt.Point",
                                    "java.awt.Rectangle"
                            };
                            for (String name : names) {
                                if (name.equals(className)) {
                                    /** 如果系統支持4中類型, 使用AwtCodec 序列化 */
                                    put(Class.forName(name), writer = AwtCodec.instance);
                                    return writer;
                                }
                            }
                        } catch (Throwable e) {
                            awtError = true;
                            // skip
                        }
                    }
                }

                // jdk8
                if ((!jdk8Error) //
                    && (className.startsWith("java.time.") //
                        || className.startsWith("java.util.Optional") //
                        || className.equals("java.util.concurrent.atomic.LongAdder")
                        || className.equals("java.util.concurrent.atomic.DoubleAdder")
                    )) {
                    try {
                        {
                            String[] names = new String[]{
                                    "java.time.LocalDateTime",
                                    "java.time.LocalDate",
                                    "java.time.LocalTime",
                                    "java.time.ZonedDateTime",
                                    "java.time.OffsetDateTime",
                                    "java.time.OffsetTime",
                                    "java.time.ZoneOffset",
                                    "java.time.ZoneRegion",
                                    "java.time.Period",
                                    "java.time.Duration",
                                    "java.time.Instant"
                            };
                            for (String name : names) {
                                if (name.equals(className)) {
                                    /** 如果系統支持JDK8中日期類型, 使用Jdk8DateCodec 序列化 */
                                    put(Class.forName(name), writer = Jdk8DateCodec.instance);
                                    return writer;
                                }
                            }
                        }
                        {
                            String[] names = new String[]{
                                    "java.util.Optional",
                                    "java.util.OptionalDouble",
                                    "java.util.OptionalInt",
                                    "java.util.OptionalLong"
                            };
                            for (String name : names) {
                                if (name.equals(className)) {
                                    /** 如果系統支持JDK8中可選類型, 使用OptionalCodec 序列化 */
                                    put(Class.forName(name), writer = OptionalCodec.instance);
                                    return writer;
                                }
                            }
                        }
                        {
                            String[] names = new String[]{
                                    "java.util.concurrent.atomic.LongAdder",
                                    "java.util.concurrent.atomic.DoubleAdder"
                            };
                            for (String name : names) {
                                if (name.equals(className)) {
                                    /** 如果系統支持JDK8中原子類型, 使用AdderSerializer 序列化 */
                                    put(Class.forName(name), writer = AdderSerializer.instance);
                                    return writer;
                                }
                            }
                        }
                    } catch (Throwable e) {
                        // skip
                        jdk8Error = true;
                    }
                }

                if ((!oracleJdbcError) //
                    && className.startsWith("oracle.sql.")) {
                    try {
                        String[] names = new String[] {
                                "oracle.sql.DATE",
                                "oracle.sql.TIMESTAMP"
                        };

                        for (String name : names) {
                            if (name.equals(className)) {
                                /** 如果系統支持oralcle驅動中日期類型, 使用DateCodec 序列化 */
                                put(Class.forName(name), writer = DateCodec.instance);
                                return writer;
                            }
                        }
                    } catch (Throwable e) {
                        // skip
                        oracleJdbcError = true;
                    }
                }

                if ((!springfoxError) //
                    && className.equals("springfox.documentation.spring.web.json.Json")) {
                    try {
                        /** 如果系統支持springfox-spring-web框架中Json類型, 使用SwaggerJsonSerializer 序列化 */
                        put(Class.forName("springfox.documentation.spring.web.json.Json"),
                                writer = SwaggerJsonSerializer.instance);
                        return writer;
                    } catch (ClassNotFoundException e) {
                        // skip
                        springfoxError = true;
                    }
                }

                if ((!guavaError) //
                        && className.startsWith("com.google.common.collect.")) {
                    try {
                        String[] names = new String[] {
                                "com.google.common.collect.HashMultimap",
                                "com.google.common.collect.LinkedListMultimap",
                                "com.google.common.collect.ArrayListMultimap",
                                "com.google.common.collect.TreeMultimap"
                        };

                        for (String name : names) {
                            if (name.equals(className)) {
                                /** 如果系統支持guava框架中日期類型, 使用GuavaCodec 序列化 */
                                put(Class.forName(name), writer = GuavaCodec.instance);
                                return writer;
                            }
                        }
                    } catch (ClassNotFoundException e) {
                        // skip
                        guavaError = true;
                    }
                }

                if ((!jsonnullError) && className.equals("net.sf.json.JSONNull")) {
                    try {
                        /** 如果系統支持json-lib框架中JSONNull類型, 使用MiscCodec 序列化 */
                        put(Class.forName("net.sf.json.JSONNull"), writer = MiscCodec.instance);
                        return writer;
                    } catch (ClassNotFoundException e) {
                        // skip
                        jsonnullError = true;
                    }
                }

                Class[] interfaces = clazz.getInterfaces();
                /** 如果class只實現唯一接口,並且接口包含註解,使用AnnotationSerializer 序列化 */
                if (interfaces.length == 1 && interfaces[0].isAnnotation()) {
                    return AnnotationSerializer.instance;
                }

                /** 如果使用了cglib或者javassist動態代理 */
                if (TypeUtils.isProxy(clazz)) {
                    Class<?> superClazz = clazz.getSuperclass();

                    /** 通過父類型查找序列化,父類是真實的類型 */
                    ObjectSerializer superWriter = getObjectWriter(superClazz);
                    put(clazz, superWriter);
                    return superWriter;
                }

                /** 如果使用了jdk動態代理 */
                if (Proxy.isProxyClass(clazz)) {
                    Class handlerClass = null;

                    if (interfaces.length == 2) {
                        handlerClass = interfaces[1];
                    } else {
                        for (Class proxiedInterface : interfaces) {
                            if (proxiedInterface.getName().startsWith("org.springframework.aop.")) {
                                continue;
                            }
                            if (handlerClass != null) {
                                handlerClass = null; // multi-matched
                                break;
                            }
                            handlerClass = proxiedInterface;
                        }
                    }

                    if (handlerClass != null) {
                        /** 根據class實現接口類型查找序列化 */
                        ObjectSerializer superWriter = getObjectWriter(handlerClass);
                        put(clazz, superWriter);
                        return superWriter;
                    }
                }

                if (create) {
                    /** 沒有精確匹配,使用通用JavaBeanSerializer 序列化(假設不啓用asm) */
                    writer = createJavaBeanSerializer(clazz);
                    put(clazz, writer);
                }
            }

            if (writer == null) {
                /** 嘗試在已註冊緩存找到特定class的序列化實例 */
                writer = serializers.get(clazz);
            }
        }
        return writer;
    }

查找具體序列化實例,查找方法基本思想根據class類型或者實現接口類型進行匹配查找。接下來針對逐個序列化實現依次分析。

序列化回調接口實現分析

內部註冊的序列化

fastjson針對常用的類型已經註冊了序列化實現方案:

    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
        SerializeWriter out = serializer.out;

        /** 當前object是boolean值, 如果爲null,
         *  並且序列化開啓WriteNullBooleanAsFalse特性, 輸出false
         */
        Boolean value = (Boolean) object;
        if (value == null) {
            out.writeNull(SerializerFeature.WriteNullBooleanAsFalse);
            return;
        }

        if (value.booleanValue()) {
            out.write("true");
        } else {
            out.write("false");
        }
    }

1 BooleanCodec序列化

其實理解了前面分析SerializeWriter, 接下來的內容比較容易理解, BooleanCodec 序列化實現 :

    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
        SerializeWriter out = serializer.out;

        /** 當前object是boolean值, 如果爲null,
         *  並且序列化開啓WriteNullBooleanAsFalse特性, 輸出false
         */
        Boolean value = (Boolean) object;
        if (value == null) {
            out.writeNull(SerializerFeature.WriteNullBooleanAsFalse);
            return;
        }

        if (value.booleanValue()) {
            out.write("true");
        } else {
            out.write("false");
        }
    }

BooleanCodec序列化實現主要判斷是否開啓如果爲null值是否輸出false,否則輸出boolean字面量值。

2 CharacterCodec序列化

    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
        SerializeWriter out = serializer.out;

        Character value = (Character) object;
        if (value == null) {
            /** 字符串爲空,輸出空字符串 */
            out.writeString("");
            return;
        }

        char c = value.charValue();
        if (c == 0) {
            /** 空白字符,輸出unicode空格字符 */
            out.writeString("\u0000");
        } else {
            /** 輸出字符串值 */
            out.writeString(value.toString());
        }
    }

3 IntegerCodec序列化

    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
        SerializeWriter out = serializer.out;

        Number value = (Number) object;

        /** 當前object是整形值, 如果爲null,
         *  並且序列化開啓WriteNullNumberAsZero特性, 輸出0
         */
        if (value == null) {
            out.writeNull(SerializerFeature.WriteNullNumberAsZero);
            return;
        }

        /** 判斷整形或者長整型,直接輸出 */
        if (object instanceof Long) {
            out.writeLong(value.longValue());
        } else {
            out.writeInt(value.intValue());
        }

        /** 如果開啓WriteClassName特性,輸出具體值類型 */
        if (out.isEnabled(SerializerFeature.WriteClassName)) {
            Class<?> clazz = value.getClass();
            if (clazz == Byte.class) {
                out.write('B');
            } else if (clazz == Short.class) {
                out.write('S');
            }
        }
    }

4 LongCodec序列化

    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
        SerializeWriter out = serializer.out;

        /** 當前object是長整形值, 如果爲null,
         *  並且序列化開啓WriteNullNumberAsZero特性, 輸出0
         */
        if (object == null) {
            out.writeNull(SerializerFeature.WriteNullNumberAsZero);
        } else {
            long value = ((Long) object).longValue();
            out.writeLong(value);

            /** 如果長整型值範圍和整型相同,顯示添加L 標識爲long */
            if (out.isEnabled(SerializerFeature.WriteClassName)
                && value <= Integer.MAX_VALUE && value >= Integer.MIN_VALUE
                && fieldType != Long.class
                && fieldType != long.class) {
                out.write('L');
            }
        }
    }

Long類型序列化會特殊標識值落在整數範圍內,如果開啓WriteClassName序列化特性,會追加L字符。

5 FloatCodec序列化

    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
        SerializeWriter out = serializer.out;

        /** 當前object是float值, 如果爲null,
         *  並且序列化開啓WriteNullNumberAsZero特性, 輸出0
         */
        if (object == null) {
            out.writeNull(SerializerFeature.WriteNullNumberAsZero);
            return;
        }

        float floatValue = ((Float) object).floatValue();
        if (decimalFormat != null) {
            /** 轉換一下浮點數值格式 */
            String floatText = decimalFormat.format(floatValue);
            out.write(floatText);
        } else {
            out.writeFloat(floatValue, true);
        }
    }

6 BigDecimalCodec序列化

    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
        SerializeWriter out = serializer.out;

        /** 當前object是BigDecimal值, 如果爲null,
         *  並且序列化開啓WriteNullNumberAsZero特性, 輸出0
         */
        if (object == null) {
            out.writeNull(SerializerFeature.WriteNullNumberAsZero);
        } else {
            BigDecimal val = (BigDecimal) object;

            String outText;
            /** 如果序列化開啓WriteBigDecimalAsPlain特性,搞定度輸出不會包含指數e */
            if (out.isEnabled(SerializerFeature.WriteBigDecimalAsPlain)) {
                outText = val.toPlainString();
            } else {
                outText = val.toString();
            }
            out.write(outText);

            if (out.isEnabled(SerializerFeature.WriteClassName) && fieldType != BigDecimal.class && val.scale() == 0) {
                out.write('.');
            }
        }
    }

7 BigIntegerCodec序列化

    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
        SerializeWriter out = serializer.out;

        /** 當前object是BigInteger值, 如果爲null,
         *  並且序列化開啓WriteNullNumberAsZero特性, 輸出0
         */
        if (object == null) {
            out.writeNull(SerializerFeature.WriteNullNumberAsZero);
            return;
        }

        BigInteger val = (BigInteger) object;
        out.write(val.toString());
    }

8 StringCodec序列化

    public void write(JSONSerializer serializer, String value) {
        SerializeWriter out = serializer.out;

        /** 當前object是string值, 如果爲null,
         *  並且序列化開啓WriteNullStringAsEmpty特性, 輸出空串""
         */
        if (value == null) {
            out.writeNull(SerializerFeature.WriteNullStringAsEmpty);
            return;
        }

        out.writeString(value);
    }

9 PrimitiveArraySerializer序列化

    public final void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
        SerializeWriter out = serializer.out;

        if (object == null) {
            /** 當前object是數組值, 如果爲null,
             *  並且序列化開啓WriteNullListAsEmpty特性, 輸出空串""
             */
            out.writeNull(SerializerFeature.WriteNullListAsEmpty);
            return;
        }

        /** 循環寫int數組 */
        if (object instanceof int[]) {
            int[] array = (int[]) object;
            out.write('[');
            for (int i = 0; i < array.length; ++i) {
                if (i != 0) {
                    out.write(',');
                }
                out.writeInt(array[i]);
            }
            out.write(']');
            return;
        }

        /** 循環寫short數組 */
        if (object instanceof short[]) {
            short[] array = (short[]) object;
            out.write('[');
            for (int i = 0; i < array.length; ++i) {
                if (i != 0) {
                    out.write(',');
                }
                out.writeInt(array[i]);
            }
            out.write(']');
            return;
        }

        /** 循環寫long數組 */
        if (object instanceof long[]) {
            long[] array = (long[]) object;

            out.write('[');
            for (int i = 0; i < array.length; ++i) {
                if (i != 0) {
                    out.write(',');
                }
                out.writeLong(array[i]);
            }
            out.write(']');
            return;
        }

        /** 循環寫boolean數組 */
        if (object instanceof boolean[]) {
            boolean[] array = (boolean[]) object;
            out.write('[');
            for (int i = 0; i < array.length; ++i) {
                if (i != 0) {
                    out.write(',');
                }
                out.write(array[i]);
            }
            out.write(']');
            return;
        }

        /** 循環寫float數組 */
        if (object instanceof float[]) {
            float[] array = (float[]) object;
            out.write('[');
            for (int i = 0; i < array.length; ++i) {
                if (i != 0) {
                    out.write(',');
                }

                float item = array[i];
                if (Float.isNaN(item)) {
                    out.writeNull();
                } else {
                    out.append(Float.toString(item));
                }
            }
            out.write(']');
            return;
        }

        /** 循環寫double數組 */
        if (object instanceof double[]) {
            double[] array = (double[]) object;
            out.write('[');
            for (int i = 0; i < array.length; ++i) {
                if (i != 0) {
                    out.write(',');
                }

                double item = array[i];
                if (Double.isNaN(item)) {
                    out.writeNull();
                } else {
                    out.append(Double.toString(item));
                }
            }
            out.write(']');
            return;
        }

        /** 寫字節數組 */
        if (object instanceof byte[]) {
            byte[] array = (byte[]) object;
            out.writeByteArray(array);
            return;
        }

        /** char數組當做字符串 */
        char[] chars = (char[]) object;
        out.writeString(chars);
    }

10 ObjectArrayCodec序列化

    public final void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features)
                                                                                                       throws IOException {
        SerializeWriter out = serializer.out;

        Object[] array = (Object[]) object;

        /** 當前object是數組對象, 如果爲null,
         *  並且序列化開啓WriteNullListAsEmpty特性, 輸出空串[]
         */
        if (object == null) {
            out.writeNull(SerializerFeature.WriteNullListAsEmpty);
            return;
        }

        int size = array.length;

        int end = size - 1;

        /** 當前object是數組對象, 如果爲沒有元素, 輸出空串[] */
        if (end == -1) {
            out.append("[]");
            return;
        }

        SerialContext context = serializer.context;
        serializer.setContext(context, object, fieldName, 0);

        try {
            Class<?> preClazz = null;
            ObjectSerializer preWriter = null;
            out.append('[');

            /**
             *  如果開啓json格式化,循環輸出數組對象,
             *  會根據數組元素class類型查找序列化實例輸出
             */
            if (out.isEnabled(SerializerFeature.PrettyFormat)) {
                serializer.incrementIndent();
                serializer.println();
                for (int i = 0; i < size; ++i) {
                    if (i != 0) {
                        out.write(',');
                        serializer.println();
                    }
                    serializer.write(array[i]);
                }
                serializer.decrementIdent();
                serializer.println();
                out.write(']');
                return;
            }

            for (int i = 0; i < end; ++i) {
                Object item = array[i];

                if (item == null) {
                    out.append("null,");
                } else {
                    if (serializer.containsReference(item)) {
                        serializer.writeReference(item);
                    } else {
                        Class<?> clazz = item.getClass();

                        /** 如果當前序列化元素和前一次class類型相同,避免再一次class類型查找序列化實例 */
                        if (clazz == preClazz) {
                            preWriter.write(serializer, item, null, null, 0);
                        } else {
                            preClazz = clazz;
                            /** 查找數組元素class類型的序列化器 序列化item */
                            preWriter = serializer.getObjectWriter(clazz);
                            preWriter.write(serializer, item, null, null, 0);
                        }
                    }
                    out.append(',');
                }
            }

            Object item = array[end];

            if (item == null) {
                out.append("null]");
            } else {
                if (serializer.containsReference(item)) {
                    serializer.writeReference(item);
                } else {
                    serializer.writeWithFieldName(item, end);
                }
                out.append(']');
            }
        } finally {
            serializer.context = context;
        }
    }

ObjectArrayCodec序列化主要判斷是否開啓格式化輸出json,如果是輸出添加適當的縮進。針對數組元素不一樣會根據元素class類型查找具體的序列化器輸出,這裏優化了如果元素相同的元素避免冗餘的查找序列化器。

11 MiscCodec序列化

    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType,
                      int features) throws IOException {
        SerializeWriter out = serializer.out;

        if (object == null) {
            out.writeNull();
            return;
        }

        Class<?> objClass = object.getClass();

        String strVal;
        if (objClass == SimpleDateFormat.class) {
            String pattern = ((SimpleDateFormat) object).toPattern();

            /** 輸出SimpleDateFormat類型的類型 */
            if (out.isEnabled(SerializerFeature.WriteClassName)) {
                if (object.getClass() != fieldType) {
                    out.write('{');
                    out.writeFieldName(JSON.DEFAULT_TYPE_KEY);
                    serializer.write(object.getClass().getName());
                    out.writeFieldValue(',', "val", pattern);
                    out.write('}');
                    return;
                }
            }

            /** 轉換SimpleDateFormat對象成pattern字符串 */
            strVal = pattern;
        } else if (objClass == Class.class) {
            Class<?> clazz = (Class<?>) object;
            /** 轉換Class對象成name字符串 */
            strVal = clazz.getName();
        } else if (objClass == InetSocketAddress.class) {
            InetSocketAddress address = (InetSocketAddress) object;

            InetAddress inetAddress = address.getAddress();
            /** 轉換InetSocketAddress對象成地址和端口字符串 */
            out.write('{');
            if (inetAddress != null) {
                out.writeFieldName("address");
                serializer.write(inetAddress);
                out.write(',');
            }
            out.writeFieldName("port");
            out.writeInt(address.getPort());
            out.write('}');
            return;
        } else if (object instanceof File) {
            /** 轉換File對象成文件路徑字符串 */
            strVal = ((File) object).getPath();
        } else if (object instanceof InetAddress) {
            /** 轉換InetAddress對象成主機地址字符串 */
            strVal = ((InetAddress) object).getHostAddress();
        } else if (object instanceof TimeZone) {
            TimeZone timeZone = (TimeZone) object;
            /** 轉換TimeZone對象成時區id字符串 */
            strVal = timeZone.getID();
        } else if (object instanceof Currency) {
            Currency currency = (Currency) object;
            /** 轉換Currency對象成幣別編碼字符串 */
            strVal = currency.getCurrencyCode();
        } else if (object instanceof JSONStreamAware) {
            JSONStreamAware aware = (JSONStreamAware) object;
            aware.writeJSONString(out);
            return;
        } else if (object instanceof Iterator) {
            Iterator<?> it = ((Iterator<?>) object);
            /** 迭代器轉換成數組碼字符串 [,,,] */
            writeIterator(serializer, out, it);
            return;
        } else if (object instanceof Iterable) {
            /** 迭代器轉換成數組碼字符串 [,,,] */
            Iterator<?> it = ((Iterable<?>) object).iterator();
            writeIterator(serializer, out, it);
            return;
        } else if (object instanceof Map.Entry) {
            Map.Entry entry = (Map.Entry) object;
            Object objKey = entry.getKey();
            Object objVal = entry.getValue();

            /** 輸出map的Entry值 */
            if (objKey instanceof String) {
                String key = (String) objKey;

                if (objVal instanceof String) {
                    String value = (String) objVal;
                    out.writeFieldValueStringWithDoubleQuoteCheck('{', key, value);
                } else {
                    out.write('{');
                    out.writeFieldName(key);
                    /** 根據value的class類型查找序列化器並輸出 */
                    serializer.write(objVal);
                }
            } else {
                /** 根據key、value的class類型查找序列化器並輸出 */
                out.write('{');
                serializer.write(objKey);
                out.write(':');
                serializer.write(objVal);
            }
            out.write('}');
            return;
        } else if (object.getClass().getName().equals("net.sf.json.JSONNull")) {
            out.writeNull();
            return;
        } else {
            throw new JSONException("not support class : " + objClass);
        }

        out.writeString(strVal);
    }

MiscCodec序列化的主要思想是吧JDK內部常用的對象簡化處理,比如TimeZone只保留id輸出,極大地降低了輸出字節大小。

12 AppendableSerializer序列化

    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {

        /** 當前object實現了Appendable接口, 如果爲null,
         *  並且序列化開啓WriteNullStringAsEmpty特性, 輸出空串""
         */
        if (object == null) {
            SerializeWriter out = serializer.out;
            out.writeNull(SerializerFeature.WriteNullStringAsEmpty);
            return;
        }

        /** 輸出對象toString結果作爲json串 */
        serializer.write(object.toString());
    }

13 ToStringSerializer序列化

    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType,
                      int features) throws IOException {
        SerializeWriter out = serializer.out;

        /** 如果爲null, 輸出空串"null" */
        if (object == null) {
            out.writeNull();
            return;
        }

        /** 輸出對象toString結果作爲json串 */
        String strVal = object.toString();
        out.writeString(strVal);
    }

14 AtomicCodec序列化

    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
        SerializeWriter out = serializer.out;

        if (object instanceof AtomicInteger) {
            AtomicInteger val = (AtomicInteger) object;
            /** 獲取整數輸出 */
            out.writeInt(val.get());
            return;
        }

        if (object instanceof AtomicLong) {
            AtomicLong val = (AtomicLong) object;
            /** 獲取長整數輸出 */
            out.writeLong(val.get());
            return;
        }

        if (object instanceof AtomicBoolean) {
            AtomicBoolean val = (AtomicBoolean) object;
            /** 獲取boolean值輸出 */
            out.append(val.get() ? "true" : "false");
            return;
        }

        /** 當前object是原子數組類型, 如果爲null,輸出[] */
        if (object == null) {
            out.writeNull(SerializerFeature.WriteNullListAsEmpty);
            return;
        }

        /** 遍歷AtomicIntegerArray,輸出int數組類型 */
        if (object instanceof AtomicIntegerArray) {
            AtomicIntegerArray array = (AtomicIntegerArray) object;
            int len = array.length();
            out.write('[');
            for (int i = 0; i < len; ++i) {
                int val = array.get(i);
                if (i != 0) {
                    out.write(',');
                }
                out.writeInt(val);
            }
            out.write(']');

            return;
        }

        /** 遍歷AtomicLongArray,輸出long數組類型 */
        AtomicLongArray array = (AtomicLongArray) object;
        int len = array.length();
        out.write('[');
        for (int i = 0; i < len; ++i) {
            long val = array.get(i);
            if (i != 0) {
                out.write(',');
            }
            out.writeLong(val);
        }
        out.write(']');
    }

15 ReferenceCodec序列化

    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
        Object item;
        /** 當前object是Reference類型,
         *  調用get()查找對應的class序列化器輸出
         */
        if (object instanceof AtomicReference) {
            AtomicReference val = (AtomicReference) object;
            item = val.get();
        } else {
            item = ((Reference) object).get();
        }
        serializer.write(item);
    }

16 CollectionCodec序列化

    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
        SerializeWriter out = serializer.out;

        /** 當前object是集合對象, 如果爲null,
         *  並且序列化開啓WriteNullListAsEmpty特性, 輸出空串[]
         */
        if (object == null) {
            out.writeNull(SerializerFeature.WriteNullListAsEmpty);
            return;
        }

        Type elementType = null;
        if (out.isEnabled(SerializerFeature.WriteClassName)
                || SerializerFeature.isEnabled(features, SerializerFeature.WriteClassName))
        {
            /** 獲取字段泛型類型 */
            elementType = TypeUtils.getCollectionItemType(fieldType);
        }

        Collection<?> collection = (Collection<?>) object;

        SerialContext context = serializer.context;
        serializer.setContext(context, object, fieldName, 0);

        if (out.isEnabled(SerializerFeature.WriteClassName)) {
            if (HashSet.class == collection.getClass()) {
                out.append("Set");
            } else if (TreeSet.class == collection.getClass()) {
                out.append("TreeSet");
            }
        }

        try {
            int i = 0;
            out.append('[');
            for (Object item : collection) {

                if (i++ != 0) {
                    out.append(',');
                }

                if (item == null) {
                    out.writeNull();
                    continue;
                }

                Class<?> clazz = item.getClass();

                /** 獲取整形類型值,輸出 */
                if (clazz == Integer.class) {
                    out.writeInt(((Integer) item).intValue());
                    continue;
                }

                /** 獲取整形長類型值,輸出並添加L標識(如果開啓WriteClassName特性) */
                if (clazz == Long.class) {
                    out.writeLong(((Long) item).longValue());

                    if (out.isEnabled(SerializerFeature.WriteClassName)) {
                        out.write('L');
                    }
                    continue;
                }

                /** 根據集合類型查找序列化實例處理,JavaBeanSerializer後面單獨分析 */
                ObjectSerializer itemSerializer = serializer.getObjectWriter(clazz);
                if (SerializerFeature.isEnabled(features, SerializerFeature.WriteClassName)
                        && itemSerializer instanceof JavaBeanSerializer) {
                    JavaBeanSerializer javaBeanSerializer = (JavaBeanSerializer) itemSerializer;
                    javaBeanSerializer.writeNoneASM(serializer, item, i - 1, elementType, features);
                } else {
                    itemSerializer.write(serializer, item, i - 1, elementType, features);
                }
            }
            out.append(']');
        } finally {
            serializer.context = context;
        }
    }

 特定序列化實現解析

 1 MapSerializer序列化

按照代碼的順序第一個分析到Map序列化器,內部調用write:

    public void write(JSONSerializer serializer
            , Object object
            , Object fieldName
            , Type fieldType
            , int features) throws IOException {
        write(serializer, object, fieldName, fieldType, features, false);
    }

進入MapSerializer#write(com.alibaba.fastjson.serializer.JSONSerializer, java.lang.Object, java.lang.Object, java.lang.reflect.Type, int, boolean)方法:
 

    public void write(JSONSerializer serializer
            , Object object
            , Object fieldName
            , Type fieldType
            , int features 
            , boolean unwrapped) throws IOException {
        SerializeWriter out = serializer.out;

        if (object == null) {
            /** 如果map是null, 輸出 "null" 字符串 */
            out.writeNull();
            return;
        }

        Map<?, ?> map = (Map<?, ?>) object;
        final int mapSortFieldMask = SerializerFeature.MapSortField.mask;
        if ((out.features & mapSortFieldMask) != 0 || (features & mapSortFieldMask) != 0) {
            /** JSONObject包裝HashMap或者LinkedHashMap */
            if (map instanceof JSONObject) {
                map = ((JSONObject) map).getInnerMap();
            }

            if ((!(map instanceof SortedMap)) && !(map instanceof LinkedHashMap)) {
                try {
                    map = new TreeMap(map);
                } catch (Exception ex) {
                    // skip
                }
            }
        }

        if (serializer.containsReference(object)) {
            /** 處理對象引用,下文詳細分析 */
            serializer.writeReference(object);
            return;
        }

        SerialContext parent = serializer.context;
        /** 創建當前新的序列化context */
        serializer.setContext(parent, object, fieldName, 0);
        try {
            if (!unwrapped) {
                out.write('{');
            }

            serializer.incrementIndent();

            Class<?> preClazz = null;
            ObjectSerializer preWriter = null;

            boolean first = true;

            if (out.isEnabled(SerializerFeature.WriteClassName)) {
                String typeKey = serializer.config.typeKey;
                Class<?> mapClass = map.getClass();
                boolean containsKey = (mapClass == JSONObject.class || mapClass == HashMap.class || mapClass == LinkedHashMap.class) 
                        && map.containsKey(typeKey);
                /** 序列化的map不包含key=@type或者自定義值,則輸出map的類名 */
                if (!containsKey) {
                    out.writeFieldName(typeKey);
                    out.writeString(object.getClass().getName());
                    first = false;
                }
            }

            for (Map.Entry entry : map.entrySet()) {
                Object value = entry.getValue();

                Object entryKey = entry.getKey();

                {
                    /** 遍歷JSONSerializer的PropertyPreFilter攔截器,攔截key是否輸出 */
                    List<PropertyPreFilter> preFilters = serializer.propertyPreFilters;
                    if (preFilters != null && preFilters.size() > 0) {
                        if (entryKey == null || entryKey instanceof String) {
                            if (!this.applyName(serializer, object, (String) entryKey)) {
                                continue;
                            }
                        } else if (entryKey.getClass().isPrimitive() || entryKey instanceof Number) {
                            String strKey = JSON.toJSONString(entryKey);
                            if (!this.applyName(serializer, object, strKey)) {
                                continue;
                            }
                        }
                    }
                }
                {
                    /** 遍歷PropertyPreFilter攔截器,攔截key是否輸出 */
                    List<PropertyPreFilter> preFilters = this.propertyPreFilters;
                    if (preFilters != null && preFilters.size() > 0) {
                        if (entryKey == null || entryKey instanceof String) {
                            if (!this.applyName(serializer, object, (String) entryKey)) {
                                continue;
                            }
                        } else if (entryKey.getClass().isPrimitive() || entryKey instanceof Number) {
                            String strKey = JSON.toJSONString(entryKey);
                            if (!this.applyName(serializer, object, strKey)) {
                                continue;
                            }
                        }
                    }
                }

                {
                    /** 遍歷JSONSerializer的PropertyFilter攔截器,攔截key是否輸出 */
                    List<PropertyFilter> propertyFilters = serializer.propertyFilters;
                    if (propertyFilters != null && propertyFilters.size() > 0) {
                        if (entryKey == null || entryKey instanceof String) {
                            if (!this.apply(serializer, object, (String) entryKey, value)) {
                                continue;
                            }
                        } else if (entryKey.getClass().isPrimitive() || entryKey instanceof Number) {
                            String strKey = JSON.toJSONString(entryKey);
                            if (!this.apply(serializer, object, strKey, value)) {
                                continue;
                            }
                        }
                    }
                }
                {
                    /** 遍歷PropertyFilter攔截器,攔截key是否輸出 */
                    List<PropertyFilter> propertyFilters = this.propertyFilters;
                    if (propertyFilters != null && propertyFilters.size() > 0) {
                        if (entryKey == null || entryKey instanceof String) {
                            if (!this.apply(serializer, object, (String) entryKey, value)) {
                                continue;
                            }
                        } else if (entryKey.getClass().isPrimitive() || entryKey instanceof Number) {
                            String strKey = JSON.toJSONString(entryKey);
                            if (!this.apply(serializer, object, strKey, value)) {
                                continue;
                            }
                        }
                    }
                }

                {
                    /** 遍歷JSONSerializer的NameFilter攔截器,適用於key字符別名串轉換 */
                    List<NameFilter> nameFilters = serializer.nameFilters;
                    if (nameFilters != null && nameFilters.size() > 0) {
                        if (entryKey == null || entryKey instanceof String) {
                            entryKey = this.processKey(serializer, object, (String) entryKey, value);
                        } else if (entryKey.getClass().isPrimitive() || entryKey instanceof Number) {
                            String strKey = JSON.toJSONString(entryKey);
                            entryKey = this.processKey(serializer, object, strKey, value);
                        }
                    }
                }
                {
                    /** 遍歷NameFilter攔截器,適用於key字符串別名轉換 */
                    List<NameFilter> nameFilters = this.nameFilters;
                    if (nameFilters != null && nameFilters.size() > 0) {
                        if (entryKey == null || entryKey instanceof String) {
                            entryKey = this.processKey(serializer, object, (String) entryKey, value);
                        } else if (entryKey.getClass().isPrimitive() || entryKey instanceof Number) {
                            String strKey = JSON.toJSONString(entryKey);
                            entryKey = this.processKey(serializer, object, strKey, value);
                        }
                    }
                }

                {
                    /** 處理map序列化value攔截器, ValueFilter 和 ContextValueFilter */
                    if (entryKey == null || entryKey instanceof String) {
                        value = this.processValue(serializer, null, object, (String) entryKey, value);
                    } else {
                        boolean objectOrArray = entryKey instanceof Map || entryKey instanceof Collection;
                        if (!objectOrArray) {
                            String strKey = JSON.toJSONString(entryKey);
                            value = this.processValue(serializer, null, object, strKey, value);
                        }
                    }
                }

                if (value == null) {
                    /** 如果開啓map爲Null,不輸出 */
                    if (!out.isEnabled(SerializerFeature.WRITE_MAP_NULL_FEATURES)) {
                        continue;
                    }
                }

                if (entryKey instanceof String) {
                    String key = (String) entryKey;

                    /** 如果不是第一個屬性字段增加分隔符 */
                    if (!first) {
                        out.write(',');
                    }

                    if (out.isEnabled(SerializerFeature.PrettyFormat)) {
                        serializer.println();
                    }
                    /** 輸出key */
                    out.writeFieldName(key, true);
                } else {
                    if (!first) {
                        out.write(',');
                    }

                    /** 開啓WriteNonStringKeyAsString, 將key做一次json串轉換 */
                    if (out.isEnabled(NON_STRINGKEY_AS_STRING) && !(entryKey instanceof Enum)) {
                        String strEntryKey = JSON.toJSONString(entryKey);
                        serializer.write(strEntryKey);
                    } else {
                        serializer.write(entryKey);
                    }

                    out.write(':');
                }

                first = false;

                if (value == null) {
                    /** 如果value爲空,輸出空值 */
                    out.writeNull();
                    continue;
                }

                Class<?> clazz = value.getClass();

                if (clazz != preClazz) {
                    preClazz = clazz;
                    preWriter = serializer.getObjectWriter(clazz);
                }

                if (SerializerFeature.isEnabled(features, SerializerFeature.WriteClassName)
                        && preWriter instanceof JavaBeanSerializer) {
                    Type valueType = null;
                    if (fieldType instanceof ParameterizedType) {
                        ParameterizedType parameterizedType = (ParameterizedType) fieldType;
                        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                        if (actualTypeArguments.length == 2) {
                            valueType = actualTypeArguments[1];
                        }
                    }

                    /** 特殊處理泛型,這裏假定泛型第二參數作爲值的真實類型 */
                    JavaBeanSerializer javaBeanSerializer = (JavaBeanSerializer) preWriter;
                    javaBeanSerializer.writeNoneASM(serializer, value, entryKey, valueType, features);
                } else {
                    /** 根據value類型的序列化器 序列化value */
                    preWriter.write(serializer, value, entryKey, null, features);
                }
            }
        } finally {
            serializer.context = parent;
        }

        serializer.decrementIdent();
        if (out.isEnabled(SerializerFeature.PrettyFormat) && map.size() > 0) {
            serializer.println();
        }

        if (!unwrapped) {
            out.write('}');
        }
    }

map序列化實現方法主要做了以下幾件事情:

1  處理對象引用,使用jdk的IdentityHashMap類嚴格判斷對象嚴格相等。
2  針對map的key和value執行攔截器操作。
3  針對value的類型,查找value的class類型序列化輸出。


序列化map處理引用的邏輯在 com.alibaba.fastjson.serializer.JSONSerializer#writeReference :
 

    public void writeReference(Object object) {
        SerialContext context = this.context;
        Object current = context.object;

        /** 如果輸出引用就是自己this, ref值爲 @ */
        if (object == current) {
            out.write("{\"$ref\":\"@\"}");
            return;
        }

        SerialContext parentContext = context.parent;

        /** 如果輸出引用就是父引用, ref值爲 .. */
        if (parentContext != null) {
            if (object == parentContext.object) {
                out.write("{\"$ref\":\"..\"}");
                return;
            }
        }

        SerialContext rootContext = context;
        /** 查找最頂層序列化context */
        for (;;) {
            if (rootContext.parent == null) {
                break;
            }
            rootContext = rootContext.parent;
        }

        if (object == rootContext.object) {
            /** 如果最頂層引用就是自己this, ref值爲 $*/
            out.write("{\"$ref\":\"$\"}");
        } else {
            /** 常規java對象引用,直接輸出 */
            out.write("{\"$ref\":\"");
            out.write(references.get(object).toString());
            out.write("\"}");
        }
    }

2 ListSerializer序列化

    public final void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features)
                                                                                                       throws IOException {

        boolean writeClassName = serializer.out.isEnabled(SerializerFeature.WriteClassName)
                || SerializerFeature.isEnabled(features, SerializerFeature.WriteClassName);

        SerializeWriter out = serializer.out;

        Type elementType = null;
        if (writeClassName) {
            /** 獲取泛型字段真實類型 */
            elementType = TypeUtils.getCollectionItemType(fieldType);
        }

        if (object == null) {
            /** 如果集合對象爲空並且開啓WriteNullListAsEmpty特性, 輸出[] */
            out.writeNull(SerializerFeature.WriteNullListAsEmpty);
            return;
        }

        List<?> list = (List<?>) object;

        if (list.size() == 0) {
            /** 如果集合對象元素爲0, 輸出[] */
            out.append("[]");
            return;
        }

        /** 創建當前新的序列化context */
        SerialContext context = serializer.context;
        serializer.setContext(context, object, fieldName, 0);

        ObjectSerializer itemSerializer = null;
        try {
            /** 判斷是否開啓json格式化 */
            if (out.isEnabled(SerializerFeature.PrettyFormat)) {
                out.append('[');
                serializer.incrementIndent();

                int i = 0;
                for (Object item : list) {
                    if (i != 0) {
                        out.append(',');
                    }

                    serializer.println();
                    if (item != null) {
                        /** 如果存在引用,輸出元素引用信息 */
                        if (serializer.containsReference(item)) {
                            serializer.writeReference(item);
                        } else {
                            /** 通過元素包含的類型查找序列化實例 */
                            itemSerializer = serializer.getObjectWriter(item.getClass());
                            SerialContext itemContext = new SerialContext(context, object, fieldName, 0, 0);
                            serializer.context = itemContext;
                            /** 根據具體序列化實例輸出 */
                            itemSerializer.write(serializer, item, i, elementType, features);
                        }
                    } else {
                        serializer.out.writeNull();
                    }
                    i++;
                }

                serializer.decrementIdent();
                serializer.println();
                out.append(']');
                return;
            }

            out.append('[');
            for (int i = 0, size = list.size(); i < size; ++i) {
                Object item = list.get(i);
                if (i != 0) {
                    out.append(',');
                }

                if (item == null) {
                    out.append("null");
                } else {
                    Class<?> clazz = item.getClass();

                    if (clazz == Integer.class) {
                        /** 元素類型如果是整數,直接輸出 */
                        out.writeInt(((Integer) item).intValue());
                    } else if (clazz == Long.class) {
                        /** 元素類型如果是長整數,直接輸出並判斷是否追加類型L */
                        long val = ((Long) item).longValue();
                        if (writeClassName) {
                            out.writeLong(val);
                            out.write('L');
                        } else {
                            out.writeLong(val);
                        }
                    } else {
                        if ((SerializerFeature.DisableCircularReferenceDetect.mask & features) != 0){
                            /** 如果禁用循環引用檢查,根據元素類型查找序列化實例輸出 */
                            itemSerializer = serializer.getObjectWriter(item.getClass());
                            itemSerializer.write(serializer, item, i, elementType, features);
                        }else {
                            if (!out.disableCircularReferenceDetect) {
                                /** 如果沒有禁用循環引用檢查,創建新的序列化上下文 */
                                SerialContext itemContext = new SerialContext(context, object, fieldName, 0, 0);
                                serializer.context = itemContext;
                            }

                            if (serializer.containsReference(item)) {
                                /** 處理對象引用 */
                                serializer.writeReference(item);
                            } else {
                                /** 根據集合類型查找序列化實例處理,JavaBeanSerializer後面單獨分析 */
                                itemSerializer = serializer.getObjectWriter(item.getClass());
                                if ((SerializerFeature.WriteClassName.mask & features) != 0
                                        && itemSerializer instanceof JavaBeanSerializer)
                                {
                                    JavaBeanSerializer javaBeanSerializer = (JavaBeanSerializer) itemSerializer;
                                    javaBeanSerializer.writeNoneASM(serializer, item, i, elementType, features);
                                } else {
                                    itemSerializer.write(serializer, item, i, elementType, features);
                                }
                            }
                        }
                    }
                }
            }
            out.append(']');
        } finally {
            serializer.context = context;
        }
    }

ListSerializer序列化主要判斷是否需要格式化json輸出,對整型和長整型進行特殊取值,如果是對象類型根據class類別查找序列化實例處理,和hessian2源碼實現原理類似。

3 DateCodec序列化

因爲日期序列化和前面已經分析的MiscCodecSimpleDateFormat相近,在此不冗餘分析,可以參考我已經添加的註釋分析。

4 JavaBeanSerializer序列化

因爲前面已經涵蓋了絕大部分fastjson序列化源碼分析,爲了節省篇幅,我準備用一個較爲複雜的序列化實現JavaBeanSerializer作爲結束這章內容

 

SerializeConfig#getObjectWriter中有一段邏輯createJavaBeanSerializer,我們針對進行細節分析 :

    public final ObjectSerializer createJavaBeanSerializer(Class<?> clazz) {
        /** 封裝序列化clazz Bean,包含字段類型等等 */
        SerializeBeanInfo beanInfo = TypeUtils.buildBeanInfo(clazz, null, propertyNamingStrategy, fieldBased);
        if (beanInfo.fields.length == 0 && Iterable.class.isAssignableFrom(clazz)) {
            /** 如果clazz是迭代器類型,使用MiscCodec序列化,會被序列化成數組 [,,,] */
            return MiscCodec.instance;
        }

        return createJavaBeanSerializer(beanInfo);
    }

我們先進TypeUtils.buildBeanInfo看看內部實現:

    public static SerializeBeanInfo buildBeanInfo(Class<?> beanType //
            , Map<String,String> aliasMap //
            , PropertyNamingStrategy propertyNamingStrategy //
            , boolean fieldBased //
    ){
        JSONType jsonType = TypeUtils.getAnnotation(beanType,JSONType.class);
        String[] orders = null;
        final int features;
        String typeName = null, typeKey = null;
        if(jsonType != null){
            orders = jsonType.orders();

            typeName = jsonType.typeName();
            if(typeName.length() == 0){
                typeName = null;
            }

            PropertyNamingStrategy jsonTypeNaming = jsonType.naming();
            if (jsonTypeNaming != PropertyNamingStrategy.CamelCase) {
                propertyNamingStrategy = jsonTypeNaming;
            }

            features = SerializerFeature.of(jsonType.serialzeFeatures());
            /** 查找類型父類是否包含JSONType註解 */
            for(Class<?> supperClass = beanType.getSuperclass()
                ; supperClass != null && supperClass != Object.class
                    ; supperClass = supperClass.getSuperclass()){
                JSONType superJsonType = TypeUtils.getAnnotation(supperClass,JSONType.class);
                if(superJsonType == null){
                    break;
                }
                typeKey = superJsonType.typeKey();
                if(typeKey.length() != 0){
                    break;
                }
            }

            /** 查找類型實現的接口是否包含JSONType註解 */
            for(Class<?> interfaceClass : beanType.getInterfaces()){
                JSONType superJsonType = TypeUtils.getAnnotation(interfaceClass,JSONType.class);
                if(superJsonType != null){
                    typeKey = superJsonType.typeKey();
                    if(typeKey.length() != 0){
                        break;
                    }
                }
            }

            if(typeKey != null && typeKey.length() == 0){
                typeKey = null;
            }
        } else{
            features = 0;
        }
        /** fieldName,field ,先生成fieldName的快照,減少之後的findField的輪詢 */
        Map<String,Field> fieldCacheMap = new HashMap<String,Field>();
        ParserConfig.parserAllFieldToCache(beanType, fieldCacheMap);
        List<FieldInfo> fieldInfoList = fieldBased
                ? computeGettersWithFieldBase(beanType, aliasMap, false, propertyNamingStrategy)
                : computeGetters(beanType, jsonType, aliasMap, fieldCacheMap, false, propertyNamingStrategy);
        FieldInfo[] fields = new FieldInfo[fieldInfoList.size()];
        fieldInfoList.toArray(fields);
        FieldInfo[] sortedFields;
        List<FieldInfo> sortedFieldList;
        if(orders != null && orders.length != 0){
            /** computeGettersWithFieldBase基於字段解析,
             *  computeGetters基於方法解析+字段解析
             */
            sortedFieldList = fieldBased
                    ? computeGettersWithFieldBase(beanType, aliasMap, true, propertyNamingStrategy) //
                    : computeGetters(beanType, jsonType, aliasMap, fieldCacheMap, true, propertyNamingStrategy);
        } else{
            sortedFieldList = new ArrayList<FieldInfo>(fieldInfoList);
            Collections.sort(sortedFieldList);
        }
        sortedFields = new FieldInfo[sortedFieldList.size()];
        sortedFieldList.toArray(sortedFields);
        if(Arrays.equals(sortedFields, fields)){
            sortedFields = fields;
        }
        /** 封裝對象的字段信息和方法信息 */
        return new SerializeBeanInfo(beanType, jsonType, typeName, typeKey, features, fields, sortedFields);
    }

在解析字段的時候有一個區別,computeGettersWithFieldBase基於字段解析而computeGetters基於方法解析(get + is 開頭方法)+字段解析。因爲兩者的解析類似,這裏只給出computeGettersWithFieldBase方法解析 :

    public static List<FieldInfo> computeGettersWithFieldBase(
            Class<?> clazz,
            Map<String,String> aliasMap,
            boolean sorted,
            PropertyNamingStrategy propertyNamingStrategy){
        Map<String,FieldInfo> fieldInfoMap = new LinkedHashMap<String,FieldInfo>();
        for(Class<?> currentClass = clazz; currentClass != null; currentClass = currentClass.getSuperclass()){
            Field[] fields = currentClass.getDeclaredFields();
            /** 遍歷clazz所有字段,把字段信息封裝成bean存儲到fieldInfoMap中*/
            computeFields(currentClass, aliasMap, propertyNamingStrategy, fieldInfoMap, fields);
        }
        /** 主要處理字段有序的邏輯 */
        return getFieldInfos(clazz, sorted, fieldInfoMap);
    }

查看computeFields邏輯:

    private static void computeFields(
            Class<?> clazz,
            Map<String,String> aliasMap,
            PropertyNamingStrategy propertyNamingStrategy,
            Map<String,FieldInfo> fieldInfoMap,
            Field[] fields){
        for(Field field : fields){
            /** 忽略靜態字段類型 */
            if(Modifier.isStatic(field.getModifiers())){
                continue;
            }
            /** 查找當前字段是否包含JSONField註解 */
            JSONField fieldAnnotation = field.getAnnotation(JSONField.class);
            int ordinal = 0, serialzeFeatures = 0, parserFeatures = 0;
            String propertyName = field.getName();
            String label = null;
            if(fieldAnnotation != null){
                /** 忽略不序列化的字段 */
                if(!fieldAnnotation.serialize()){
                    continue;
                }
                /** 獲取字段序列化順序 */
                ordinal = fieldAnnotation.ordinal();
                serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures());
                parserFeatures = Feature.of(fieldAnnotation.parseFeatures());
                if(fieldAnnotation.name().length() != 0){
                    /** 屬性名字採用JSONField註解上面的name */
                    propertyName = fieldAnnotation.name();
                }
                if(fieldAnnotation.label().length() != 0){
                    label = fieldAnnotation.label();
                }
            }
            if(aliasMap != null){
                /** 查找是否包含屬性別名的字段 */
                propertyName = aliasMap.get(propertyName);
                if(propertyName == null){
                    continue;
                }
            }
            if(propertyNamingStrategy != null){
                /** 屬性字段命名規則轉換 */
                propertyName = propertyNamingStrategy.translate(propertyName);
            }

            /** 封裝解析類型的字段和類型 */
            if(!fieldInfoMap.containsKey(propertyName)){
                FieldInfo fieldInfo = new FieldInfo(propertyName, null, field, clazz, null, ordinal, serialzeFeatures, parserFeatures,
                        null, fieldAnnotation, label);
                fieldInfoMap.put(propertyName, fieldInfo);
            }
        }
    }

處理字段有序的邏輯getFieldInfos :

   private static List<FieldInfo> getFieldInfos(Class<?> clazz, boolean sorted, Map<String,FieldInfo> fieldInfoMap){
        List<FieldInfo> fieldInfoList = new ArrayList<FieldInfo>();
        String[] orders = null;
        /** 查找clazz上面的JSONType註解 */
        JSONType annotation = TypeUtils.getAnnotation(clazz,JSONType.class);
        if(annotation != null){
            orders = annotation.orders();
        }
        if(orders != null && orders.length > 0){
            LinkedHashMap<String,FieldInfo> map = new LinkedHashMap<String,FieldInfo>(fieldInfoList.size());
            for(FieldInfo field : fieldInfoMap.values()){
                map.put(field.name, field);
            }
            int i = 0;
            /** 先把有序字段從map移除,並添加到有序列表fieldInfoList中 */
            for(String item : orders){
                FieldInfo field = map.get(item);
                if(field != null){
                    fieldInfoList.add(field);
                    map.remove(item);
                }
            }
            /** 將map剩餘元素追加到有序列表末尾 */
            for(FieldInfo field : map.values()){
                fieldInfoList.add(field);
            }
        } else{
            /** 如果註解沒有要求順序,全部添加map元素 */
            for(FieldInfo fieldInfo : fieldInfoMap.values()){
                fieldInfoList.add(fieldInfo);
            }
            if(sorted){
                Collections.sort(fieldInfoList);
            }
        }
        return fieldInfoList;
    }

我們在看下具體創建JavaBeanSerializer序列化邏輯:

    public ObjectSerializer createJavaBeanSerializer(SerializeBeanInfo beanInfo) {
        JSONType jsonType = beanInfo.jsonType;

        boolean asm = this.asm && !fieldBased;

        if (jsonType != null) {
            Class<?> serializerClass = jsonType.serializer();
            if (serializerClass != Void.class) {
                try {
                    /** 實例化註解指定的類型 */
                    Object seralizer = serializerClass.newInstance();
                    if (seralizer instanceof ObjectSerializer) {
                        return (ObjectSerializer) seralizer;
                    }
                } catch (Throwable e) {
                    // skip
                }
            }

            /** 註解顯示指定不使用asm */
            if (jsonType.asm() == false) {
                asm = false;
            }

            /** 註解顯示開啓WriteNonStringValueAsString、WriteEnumUsingToString
             * 和NotWriteDefaultValue不使用asm */
            for (SerializerFeature feature : jsonType.serialzeFeatures()) {
                if (SerializerFeature.WriteNonStringValueAsString == feature //
                        || SerializerFeature.WriteEnumUsingToString == feature //
                        || SerializerFeature.NotWriteDefaultValue == feature) {
                    asm = false;
                    break;
                }
            }
        }

        Class<?> clazz = beanInfo.beanType;
        /** 非public類型,直接使用JavaBeanSerializer序列化 */
        if (!Modifier.isPublic(beanInfo.beanType.getModifiers())) {
            return new JavaBeanSerializer(beanInfo);
        }

        // ... 省略asm判斷檢查

        if (asm) {
            try {
                /** 使用asm字節碼庫序列化,後面單獨列一個章節分析asm源碼 */
                ObjectSerializer asmSerializer = createASMSerializer(beanInfo);
                if (asmSerializer != null) {
                    return asmSerializer;
                }
            } catch (ClassNotFoundException ex) {
                // skip
            } catch (ClassFormatError e) {
                // skip
            } catch (ClassCastException e) {
                // skip
            } catch (Throwable e) {
                throw new JSONException("create asm serializer error, class "
                        + clazz, e);
            }
        }

        /** 默認使用JavaBeanSerializer 序列化類 */
        return new JavaBeanSerializer(beanInfo);
    }

OK, 一切就緒,接下來有請JavaBeanSerializer序列化實現登場:

    protected void write(JSONSerializer serializer, 
                      Object object, 
                      Object fieldName, 
                      Type fieldType, 
                      int features,
                      boolean unwrapped
    ) throws IOException {
        SerializeWriter out = serializer.out;

        if (object == null) {
            out.writeNull();
            return;
        }

        /** 如果開啓循環引用檢查,輸出引用並返回 */
        if (writeReference(serializer, object, features)) {
            return;
        }

        final FieldSerializer[] getters;

        if (out.sortField) {
            getters = this.sortedGetters;
        } else {
            getters = this.getters;
        }

        SerialContext parent = serializer.context;
        if (!this.beanInfo.beanType.isEnum()) {
            /** 針對非枚舉類型,創建新的上下文 */
            serializer.setContext(parent, object, fieldName, this.beanInfo.features, features);
        }

        final boolean writeAsArray = isWriteAsArray(serializer, features);

        try {
            final char startSeperator = writeAsArray ? '[' : '{';
            final char endSeperator = writeAsArray ? ']' : '}';
            if (!unwrapped) {
                out.append(startSeperator);
            }

            if (getters.length > 0 && out.isEnabled(SerializerFeature.PrettyFormat)) {
                serializer.incrementIndent();
                serializer.println();
            }

            boolean commaFlag = false;

            if ((this.beanInfo.features & SerializerFeature.WriteClassName.mask) != 0
                ||(features & SerializerFeature.WriteClassName.mask) != 0
                || serializer.isWriteClassName(fieldType, object)) {
                Class<?> objClass = object.getClass();

                final Type type;
                /** 獲取字段的泛型類型 */
                if (objClass != fieldType && fieldType instanceof WildcardType) {
                    type = TypeUtils.getClass(fieldType);
                } else {
                    type = fieldType;
                }

                if (objClass != type) {
                    /** 輸出字段類型名字 */
                    writeClassName(serializer, beanInfo.typeKey, object);
                    commaFlag = true;
                }
            }

            char seperator = commaFlag ? ',' : '\0';

            final boolean directWritePrefix = out.quoteFieldNames && !out.useSingleQuotes;
            /** 觸發序列化BeforeFilter攔截器 */
            char newSeperator = this.writeBefore(serializer, object, seperator);
            commaFlag = newSeperator == ',';

            final boolean skipTransient = out.isEnabled(SerializerFeature.SkipTransientField);
            final boolean ignoreNonFieldGetter = out.isEnabled(SerializerFeature.IgnoreNonFieldGetter);

            for (int i = 0; i < getters.length; ++i) {
                FieldSerializer fieldSerializer = getters[i];

                Field field = fieldSerializer.fieldInfo.field;
                FieldInfo fieldInfo = fieldSerializer.fieldInfo;
                String fieldInfoName = fieldInfo.name;
                Class<?> fieldClass = fieldInfo.fieldClass;

                /** 忽略配置了transient關鍵字的字段 */
                if (skipTransient) {
                    if (field != null) {
                        if (fieldInfo.fieldTransient) {
                            continue;
                        }
                    }
                }

                /** 目前看到註解方法上面 field = null */
                if (ignoreNonFieldGetter) {
                    if (field == null) {
                        continue;
                    }
                }

                boolean notApply = false;
                /** 觸發字段PropertyPreFilter攔截器 */
                if ((!this.applyName(serializer, object, fieldInfoName))
                    || !this.applyLabel(serializer, fieldInfo.label)) {
                    if (writeAsArray) {
                        notApply = true;
                    } else {
                        continue;
                    }
                }

                /** ??? */
                if (beanInfo.typeKey != null
                        && fieldInfoName.equals(beanInfo.typeKey)
                        && serializer.isWriteClassName(fieldType, object)) {
                    continue;
                }

                Object propertyValue;

                if (notApply) {
                    propertyValue = null;
                } else {
                    try {
                        propertyValue = fieldSerializer.getPropertyValueDirect(object);
                    } catch (InvocationTargetException ex) {
                        if (out.isEnabled(SerializerFeature.IgnoreErrorGetter)) {
                            propertyValue = null;
                        } else {
                            throw ex;
                        }
                    }
                }

                /** 針對屬性名字和屬性值 觸發PropertyFilter攔截器 */
                if (!this.apply(serializer, object, fieldInfoName, propertyValue)) {
                    continue;
                }

                if (fieldClass == String.class && "trim".equals(fieldInfo.format)) {
                    /** 剔除字符串兩邊空格 */
                    if (propertyValue != null) {
                        propertyValue = ((String) propertyValue).trim();
                    }
                }

                String key = fieldInfoName;
                /** 觸發屬性名字NameFilter攔截器 */
                key = this.processKey(serializer, object, key, propertyValue);

                Object originalValue = propertyValue;
                /** 觸發屬性值ContextValueFilter攔截器 */
                propertyValue = this.processValue(serializer, fieldSerializer.fieldContext, object, fieldInfoName,
                                                        propertyValue);

                if (propertyValue == null) {
                    int serialzeFeatures = fieldInfo.serialzeFeatures;
                    if (beanInfo.jsonType != null) {
                        serialzeFeatures |= SerializerFeature.of(beanInfo.jsonType.serialzeFeatures());
                    }
                    // beanInfo.jsonType
                    if (fieldClass == Boolean.class) {
                        int defaultMask = SerializerFeature.WriteNullBooleanAsFalse.mask;
                        final int mask = defaultMask | SerializerFeature.WriteMapNullValue.mask;
                        if ((!writeAsArray) && (serialzeFeatures & mask) == 0 && (out.features & mask) == 0) {
                            continue;
                            /** 針對Boolean類型,值爲空,輸出false */
                        } else if ((serialzeFeatures & defaultMask) != 0 || (out.features & defaultMask) != 0) {
                            propertyValue = false;
                        }
                    } else if (fieldClass == String.class) {
                        int defaultMask = SerializerFeature.WriteNullStringAsEmpty.mask;
                        final int mask = defaultMask | SerializerFeature.WriteMapNullValue.mask;
                        if ((!writeAsArray) && (serialzeFeatures & mask) == 0 && (out.features & mask) == 0) {
                            continue;
                        } else if ((serialzeFeatures & defaultMask) != 0 || (out.features & defaultMask) != 0) {
                            /** 針對string類型,值爲空,輸出空串"" */
                            propertyValue = "";
                        }
                    } else if (Number.class.isAssignableFrom(fieldClass)) {
                        int defaultMask = SerializerFeature.WriteNullNumberAsZero.mask;
                        final int mask = defaultMask | SerializerFeature.WriteMapNullValue.mask;
                        if ((!writeAsArray) && (serialzeFeatures & mask) == 0 && (out.features & mask) == 0) {
                            continue;
                        } else if ((serialzeFeatures & defaultMask) != 0 || (out.features & defaultMask) != 0) {
                            /** 針對數字類型,值爲空,輸出0 */
                            propertyValue = 0;
                        }
                    } else if (Collection.class.isAssignableFrom(fieldClass)) {
                        int defaultMask = SerializerFeature.WriteNullListAsEmpty.mask;
                        final int mask = defaultMask | SerializerFeature.WriteMapNullValue.mask;
                        if ((!writeAsArray) && (serialzeFeatures & mask) == 0 && (out.features & mask) == 0) {
                            continue;
                        } else if ((serialzeFeatures & defaultMask) != 0 || (out.features & defaultMask) != 0) {
                            propertyValue = Collections.emptyList();
                        }
                        /** 針對值爲null,配置序列化不輸出特性,則輸出json字符串排除這些屬性 */
                    } else if ((!writeAsArray) && (!fieldSerializer.writeNull) && !out.isEnabled(SerializerFeature.WriteMapNullValue.mask)){
                        continue;
                    }
                }

                /** 忽略序列化配置爲不輸出默認值的字段 */
                if (propertyValue != null
                        && (out.notWriteDefaultValue
                        || (fieldInfo.serialzeFeatures & SerializerFeature.NotWriteDefaultValue.mask) != 0
                        || (beanInfo.features & SerializerFeature.NotWriteDefaultValue.mask) != 0
                        )) {
                    Class<?> fieldCLass = fieldInfo.fieldClass;
                    if (fieldCLass == byte.class && propertyValue instanceof Byte
                        && ((Byte) propertyValue).byteValue() == 0) {
                        continue;
                    } else if (fieldCLass == short.class && propertyValue instanceof Short
                               && ((Short) propertyValue).shortValue() == 0) {
                        continue;
                    } else if (fieldCLass == int.class && propertyValue instanceof Integer
                               && ((Integer) propertyValue).intValue() == 0) {
                        continue;
                    } else if (fieldCLass == long.class && propertyValue instanceof Long
                               && ((Long) propertyValue).longValue() == 0L) {
                        continue;
                    } else if (fieldCLass == float.class && propertyValue instanceof Float
                               && ((Float) propertyValue).floatValue() == 0F) {
                        continue;
                    } else if (fieldCLass == double.class && propertyValue instanceof Double
                               && ((Double) propertyValue).doubleValue() == 0D) {
                        continue;
                    } else if (fieldCLass == boolean.class && propertyValue instanceof Boolean
                               && !((Boolean) propertyValue).booleanValue()) {
                        continue;
                    }
                }

                if (commaFlag) {
                    if (fieldInfo.unwrapped
                            && propertyValue instanceof Map
                            && ((Map) propertyValue).size() == 0) {
                        continue;
                    }

                    out.write(',');
                    if (out.isEnabled(SerializerFeature.PrettyFormat)) {
                        serializer.println();
                    }
                }

                /** 應用攔截器後變更了key */
                if (key != fieldInfoName) {
                    if (!writeAsArray) {
                        out.writeFieldName(key, true);
                    }

                    serializer.write(propertyValue);
                } else if (originalValue != propertyValue) {
                    if (!writeAsArray) {
                        fieldSerializer.writePrefix(serializer);
                    }
                    /** 應用攔截器後變更了屬性值,查找value的class類型進行序列化 */
                    serializer.write(propertyValue);
                } else {
                    if (!writeAsArray) {
                        /** 輸出屬性字段名稱 */
                        if (!fieldInfo.unwrapped) {
                            if (directWritePrefix) {
                                out.write(fieldInfo.name_chars, 0, fieldInfo.name_chars.length);
                            } else {
                                fieldSerializer.writePrefix(serializer);
                            }
                        }
                    }

                    if (!writeAsArray) {
                        JSONField fieldAnnotation = fieldInfo.getAnnotation();
                        if (fieldClass == String.class && (fieldAnnotation == null || fieldAnnotation.serializeUsing() == Void.class)) {

                            /** 處理針對字符串類型屬性值輸出 */
                            if (propertyValue == null) {
                                if ((out.features & SerializerFeature.WriteNullStringAsEmpty.mask) != 0
                                    || (fieldSerializer.features & SerializerFeature.WriteNullStringAsEmpty.mask) != 0) {
                                    out.writeString("");
                                } else {
                                    out.writeNull();
                                }
                            } else {
                                String propertyValueString = (String) propertyValue;

                                if (out.useSingleQuotes) {
                                    out.writeStringWithSingleQuote(propertyValueString);
                                } else {
                                    out.writeStringWithDoubleQuote(propertyValueString, (char) 0);
                                }
                            }
                        } else {
                            if (fieldInfo.unwrapped
                                    && propertyValue instanceof Map
                                    && ((Map) propertyValue).size() == 0) {
                                commaFlag = false;
                                continue;
                            }

                            fieldSerializer.writeValue(serializer, propertyValue);
                        }
                    } else {
                        /** 基於數組形式輸出 [,,,] */
                        fieldSerializer.writeValue(serializer, propertyValue);
                    }
                }

                boolean fieldUnwrappedNull = false;
                if (fieldInfo.unwrapped
                        && propertyValue instanceof Map) {
                    Map map = ((Map) propertyValue);
                    if (map.size() == 0) {
                        fieldUnwrappedNull = true;
                    } else if (!serializer.isEnabled(SerializerFeature.WriteMapNullValue)){
                        boolean hasNotNull = false;
                        for (Object value : map.values()) {
                            if (value != null) {
                                hasNotNull = true;
                                break;
                            }
                        }
                        if (!hasNotNull) {
                            fieldUnwrappedNull = true;
                        }
                    }
                }

                if (!fieldUnwrappedNull) {
                    commaFlag = true;
                }
            }

            /** 觸發序列化AfterFilter攔截器 */
            this.writeAfter(serializer, object, commaFlag ? ',' : '\0');

            if (getters.length > 0 && out.isEnabled(SerializerFeature.PrettyFormat)) {
                serializer.decrementIdent();
                serializer.println();
            }

            if (!unwrapped) {
                out.append(endSeperator);
            }
        } catch (Exception e) {
            String errorMessage = "write javaBean error, fastjson version " + JSON.VERSION;
            if (object != null) {
                errorMessage += ", class " + object.getClass().getName();
            }
            if (fieldName != null) {
                errorMessage += ", fieldName : " + fieldName;
            }
            if (e.getMessage() != null) {
                errorMessage += (", " + e.getMessage());
            }

            throw new JSONException(errorMessage, e);
        } finally {
            serializer.context = parent;
        }
    }

在序列化過程中我們重點關注一下序列化屬性值的邏輯fieldSerializer.writeValue(serializer, propertyValue)

    public void writeValue(JSONSerializer serializer, Object propertyValue) throws Exception {
        if (runtimeInfo == null) {

            Class<?> runtimeFieldClass;
            /** 獲取字段的類型 */
            if (propertyValue == null) {
                runtimeFieldClass = this.fieldInfo.fieldClass;
            } else {
                runtimeFieldClass = propertyValue.getClass();
            }

            ObjectSerializer fieldSerializer = null;
            JSONField fieldAnnotation = fieldInfo.getAnnotation();

            /** 創建並初始化字段指定序列化類型 */
            if (fieldAnnotation != null && fieldAnnotation.serializeUsing() != Void.class) {
                fieldSerializer = (ObjectSerializer) fieldAnnotation.serializeUsing().newInstance();
                serializeUsing = true;
            } else {
                /** 針對format和primitive類型創建序列化類型 */
                if (format != null) {
                    if (runtimeFieldClass == double.class || runtimeFieldClass == Double.class) {
                        fieldSerializer = new DoubleSerializer(format);
                    } else if (runtimeFieldClass == float.class || runtimeFieldClass == Float.class) {
                        fieldSerializer = new FloatCodec(format);
                    }
                }

                if (fieldSerializer == null) {
                    /** 根據屬性值class類型查找序列化類型 */
                    fieldSerializer = serializer.getObjectWriter(runtimeFieldClass);
                }
            }

            /** 封裝序列化類型和屬性值的類型 */
            runtimeInfo = new RuntimeSerializerInfo(fieldSerializer, runtimeFieldClass);
        }

        final RuntimeSerializerInfo runtimeInfo = this.runtimeInfo;

        final int fieldFeatures = disableCircularReferenceDetect?
                (fieldInfo.serialzeFeatures|SerializerFeature.DisableCircularReferenceDetect.getMask()):fieldInfo.serialzeFeatures;

        if (propertyValue == null) {
            SerializeWriter out  = serializer.out;

            if (fieldInfo.fieldClass == Object.class
                    && out.isEnabled(SerializerFeature.WRITE_MAP_NULL_FEATURES)) {
                out.writeNull();
                return;
            }

            /** 針對屬性值爲null的情況處理 */
            Class<?> runtimeFieldClass = runtimeInfo.runtimeFieldClass;

            if (Number.class.isAssignableFrom(runtimeFieldClass)) {
                out.writeNull(features, SerializerFeature.WriteNullNumberAsZero.mask);
                return;
            } else if (String.class == runtimeFieldClass) {
                out.writeNull(features, SerializerFeature.WriteNullStringAsEmpty.mask);
                return;
            } else if (Boolean.class == runtimeFieldClass) {
                out.writeNull(features, SerializerFeature.WriteNullBooleanAsFalse.mask);
                return;
            } else if (Collection.class.isAssignableFrom(runtimeFieldClass)) {
                out.writeNull(features, SerializerFeature.WriteNullListAsEmpty.mask);
                return;
            }

            ObjectSerializer fieldSerializer = runtimeInfo.fieldSerializer;

            if ((out.isEnabled(SerializerFeature.WRITE_MAP_NULL_FEATURES))
                    && fieldSerializer instanceof JavaBeanSerializer) {
                out.writeNull();
                return;
            }

            /** 序列化null對象 */
            fieldSerializer.write(serializer, null, fieldInfo.name, fieldInfo.fieldType, fieldFeatures);
            return;
        }

        if (fieldInfo.isEnum) {
            if (writeEnumUsingName) {
                /** 使用枚舉名字序列化 */
                serializer.out.writeString(((Enum<?>) propertyValue).name());
                return;
            }

            if (writeEnumUsingToString) {
                /** 使用枚舉toString字符串序列化 */
                serializer.out.writeString(((Enum<?>) propertyValue).toString());
                return;
            }
        }

        Class<?> valueClass = propertyValue.getClass();
        ObjectSerializer valueSerializer;
        if (valueClass == runtimeInfo.runtimeFieldClass || serializeUsing) {
            /** 使用序列化註解指定的序列化類型 */
            valueSerializer = runtimeInfo.fieldSerializer;
        } else {
            valueSerializer = serializer.getObjectWriter(valueClass);
        }

        if (format != null && !(valueSerializer instanceof DoubleSerializer || valueSerializer instanceof FloatCodec)) {
            if (valueSerializer instanceof ContextObjectSerializer) {
                ((ContextObjectSerializer) valueSerializer).write(serializer, propertyValue, this.fieldContext);    
            } else {
                serializer.writeWithFormat(propertyValue, format);
            }
            return;
        }

        /** 特殊檢查是否是具體類型序列化JavaBeanSerializer、 MapSerializer */
        if (fieldInfo.unwrapped) {
            if (valueSerializer instanceof JavaBeanSerializer) {
                JavaBeanSerializer javaBeanSerializer = (JavaBeanSerializer) valueSerializer;
                javaBeanSerializer.write(serializer, propertyValue, fieldInfo.name, fieldInfo.fieldType, fieldFeatures, true);
                return;
            }

            if (valueSerializer instanceof MapSerializer) {
                MapSerializer mapSerializer = (MapSerializer) valueSerializer;
                mapSerializer.write(serializer, propertyValue, fieldInfo.name, fieldInfo.fieldType, fieldFeatures, true);
                return;
            }
        }

        /** 針對字段類型和屬性值類型不一致退化成使用JavaBeanSerializer */
        if ((features & SerializerFeature.WriteClassName.mask) != 0
                && valueClass != fieldInfo.fieldClass
                && JavaBeanSerializer.class.isInstance(valueSerializer)) {
            ((JavaBeanSerializer) valueSerializer).write(serializer, propertyValue, fieldInfo.name, fieldInfo.fieldType, fieldFeatures, false);
            return;
        }

        /** 使用值序列化類型處理 */
        valueSerializer.write(serializer, propertyValue, fieldInfo.name, fieldInfo.fieldType, fieldFeatures);
    }

到此序列化成json字符串已經全部講完了,接下來講解反序列化內容

 

反序列化

反序列化的章節比序列化複雜一些,我認爲通過調試小單元代碼片段的方式有助於理解,我在適當的地方會給出單元測試入口,集中精力理解具體類型的實現。

現在,我們正式開始理解反序列化實現吧。

    public static <T> T parseObject(String text, Class<T> clazz) {
        /** 根據指定text,返回期望的java對象類型class */
        return parseObject(text, clazz, new Feature[0]);
    }

這個反序列化接口可以處理對象包含任意字段類型,但是自身不能是泛型類型,原因是java的運行時類型擦除。fastjson給出了替代方法解決:

   String json = "[{},...]";
   Type listType = new TypeReference<List<Model>>() {}.getType();
   List<Model> modelList = JSON.parseObject(json, listType);

我們把關注點收回來,繼續分析內部調用parseObject :

    public static <T> T parseObject(String json, Class<T> clazz, Feature... features) {
        return (T) parseObject(json, (Type) clazz, ParserConfig.global, null, DEFAULT_PARSER_FEATURE, features);
    }

        public static <T> T parseObject(String input, Type clazz, ParserConfig config, ParseProcess processor,
                                          int featureValues, Feature... features) {
        if (input == null) {
            return null;
        }

        /** 配置反序列化時啓用的特性,比如是否允許json字符串字段不包含雙引號 */
        if (features != null) {
            for (Feature feature : features) {
                featureValues |= feature.mask;
            }
        }

        /**
         *  初始化DefaultJSONParser,反序列化類型由它
         *  委託config查找具體序列化處理器處理
         */
        DefaultJSONParser parser = new DefaultJSONParser(input, config, featureValues);

        /** 添加攔截器 */
        if (processor != null) {
            if (processor instanceof ExtraTypeProvider) {
                parser.getExtraTypeProviders().add((ExtraTypeProvider) processor);
            }

            if (processor instanceof ExtraProcessor) {
                parser.getExtraProcessors().add((ExtraProcessor) processor);
            }

            if (processor instanceof FieldTypeResolver) {
                parser.setFieldTypeResolver((FieldTypeResolver) processor);
            }
        }

        /** 使用反序列化實例轉換對象,查找具體序列化實例委託給config查找 */
        T value = (T) parser.parseObject(clazz, null);

        /** 處理json內部引用協議格式對象 */
        parser.handleResovleTask(value);

        parser.close();

        return (T) value;
    }

最終反序列化接口定義了執行的大框架:

1  創建解析配置ParserConfig對象,包括初始化內部反序列化實例和特性配置等。
2  添加反序列化攔截器
3  根據具體類型查找反序列化實例,執行反序列化轉換
4  解析對象內部引用


我們繼續查看parser.parseObject(clazz, null)邏輯:
 

    public <T> T parseObject(Type type, Object fieldName) {
        /** 獲取json串第一個有效token */
        int token = lexer.token();
        if (token == JSONToken.NULL) {
            /** 如果返回時null,自動預讀下一個token */
            lexer.nextToken();
            return null;
        }

        /** 判定token屬於字符串 */
        if (token == JSONToken.LITERAL_STRING) {
            /** 獲取byte字節數據,分爲十六進制和base64編碼 */
            if (type == byte[].class) {
                byte[] bytes = lexer.bytesValue();
                lexer.nextToken();
                return (T) bytes;
            }

            /** 獲取字符數組, 特殊處理String內存佔用 */
            if (type == char[].class) {
                String strVal = lexer.stringVal();
                lexer.nextToken();
                return (T) strVal.toCharArray();
            }
        }

        /** 委託config進行特定類型查找反序列化實例 */
        ObjectDeserializer derializer = config.getDeserializer(type);

        try {
            /** 執行反序列化 */
            return (T) derializer.deserialze(this, type, fieldName);
        } catch (JSONException e) {
            throw e;
        } catch (Throwable e) {
            throw new JSONException(e.getMessage(), e);
        }
    }

反序列化核心邏輯還是在委託配置查找反序列化實例,我們具體看看是如何查找反序列化實例的, 進入ParserConfig#getDeserializer(java.lang.reflect.Type)自己查看邏輯:

    public ObjectDeserializer getDeserializer(Type type) {
        /** 首先從內部已經註冊查找特定class的反序列化實例 */
        ObjectDeserializer derializer = this.deserializers.get(type);
        if (derializer != null) {
            return derializer;
        }

        if (type instanceof Class<?>) {
            /** 引用類型,根據特定類型再次匹配 */
            return getDeserializer((Class<?>) type, type);
        }

        if (type instanceof ParameterizedType) {
            /** 獲取泛型類型原始類型 */
            Type rawType = ((ParameterizedType) type).getRawType();
            /** 泛型原始類型是引用類型,根據特定類型再次匹配 */
            if (rawType instanceof Class<?>) {
                return getDeserializer((Class<?>) rawType, type);
            } else {
                /** 遞歸調用反序列化查找 */
                return getDeserializer(rawType);
            }
        }

        if (type instanceof WildcardType) {
            /** 類型是通配符或者限定類型 */
            WildcardType wildcardType = (WildcardType) type;
            Type[] upperBounds = wildcardType.getUpperBounds();
            if (upperBounds.length == 1) {
                Type upperBoundType = upperBounds[0];
                /** 獲取泛型上界(? extends T),根據特定類型再次匹配 */
                return getDeserializer(upperBoundType);
            }
        }

        /** 如果無法匹配到,使用默認JavaObjectDeserializer反序列化 */
        return JavaObjectDeserializer.instance;
    }

反序列化匹配getDeserializer(Type)主要特定處理了泛型類型,取出泛型類型真實類型還是委託內部ParserConfig#getDeserializer(java.lang.Class<?>, java.lang.reflect.Type)進行精確類型查找:

 

    public ObjectDeserializer getDeserializer(Class<?> clazz, Type type) {
        /** 首先從內部已經註冊查找特定type的反序列化實例 */
        ObjectDeserializer derializer = deserializers.get(type);
        if (derializer != null) {
            return derializer;
        }

        if (type == null) {
            type = clazz;
        }

        /** 再次從內部已經註冊查找特定class的反序列化實例 */
        derializer = deserializers.get(type);
        if (derializer != null) {
            return derializer;
        }

        {
            JSONType annotation = TypeUtils.getAnnotation(clazz,JSONType.class);
            if (annotation != null) {
                Class<?> mappingTo = annotation.mappingTo();
                /** 根據類型註解指定的反序列化類型 */
                if (mappingTo != Void.class) {
                    return getDeserializer(mappingTo, mappingTo);
                }
            }
        }

        if (type instanceof WildcardType || type instanceof TypeVariable || type instanceof ParameterizedType) {
            /** 根據泛型真實類型查找反序列化實例 */
            derializer = deserializers.get(clazz);
        }

        if (derializer != null) {
            return derializer;
        }

        /** 獲取class名稱,進行類型匹配(可以支持高版本jdk和三方庫) */
        String className = clazz.getName();
        className = className.replace('$', '.');

        if (className.startsWith("java.awt.")
            && AwtCodec.support(clazz)) {
            /**
             *  如果class的name是"java.awt."開頭 並且
             *  繼承 Point、Rectangle、Font或者Color 其中之一
             */
            if (!awtError) {
                String[] names = new String[] {
                        "java.awt.Point",
                        "java.awt.Font",
                        "java.awt.Rectangle",
                        "java.awt.Color"
                };

                try {
                    for (String name : names) {
                        if (name.equals(className)) {
                            /** 如果系統支持4中類型, 使用AwtCodec 反序列化 */
                            deserializers.put(Class.forName(name), derializer = AwtCodec.instance);
                            return derializer;
                        }
                    }
                } catch (Throwable e) {
                    // skip
                    awtError = true;
                }

                derializer = AwtCodec.instance;
            }
        }

        if (!jdk8Error) {
            try {
                if (className.startsWith("java.time.")) {
                    String[] names = new String[] {
                            "java.time.LocalDateTime",
                            "java.time.LocalDate",
                            "java.time.LocalTime",
                            "java.time.ZonedDateTime",
                            "java.time.OffsetDateTime",
                            "java.time.OffsetTime",
                            "java.time.ZoneOffset",
                            "java.time.ZoneRegion",
                            "java.time.ZoneId",
                            "java.time.Period",
                            "java.time.Duration",
                            "java.time.Instant"
                    };

                    for (String name : names) {
                        if (name.equals(className)) {
                            /** 如果系統支持JDK8中日期類型, 使用Jdk8DateCodec 反序列化 */
                            deserializers.put(Class.forName(name), derializer = Jdk8DateCodec.instance);
                            return derializer;
                        }
                    }
                } else if (className.startsWith("java.util.Optional")) {
                    String[] names = new String[] {
                            "java.util.Optional",
                            "java.util.OptionalDouble",
                            "java.util.OptionalInt",
                            "java.util.OptionalLong"
                    };
                    for (String name : names) {
                        if (name.equals(className)) {
                            /** 如果系統支持JDK8中可選類型, 使用OptionalCodec 反序列化 */
                            deserializers.put(Class.forName(name), derializer = OptionalCodec.instance);
                            return derializer;
                        }
                    }
                }
            } catch (Throwable e) {
                // skip
                jdk8Error = true;
            }
        }

        if (className.equals("java.nio.file.Path")) {
            deserializers.put(clazz, derializer = MiscCodec.instance);
        }

        if (clazz == Map.Entry.class) {
            deserializers.put(clazz, derializer = MiscCodec.instance);
        }

        final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        try {
            /** 使用當前線程類加載器 查找 META-INF/services/AutowiredObjectDeserializer.class實現類 */
            for (AutowiredObjectDeserializer autowired : ServiceLoader.load(AutowiredObjectDeserializer.class,
                                                                            classLoader)) {
                for (Type forType : autowired.getAutowiredFor()) {
                    deserializers.put(forType, autowired);
                }
            }
        } catch (Exception ex) {
            // skip
        }

        if (derializer == null) {
            derializer = deserializers.get(type);
        }

        if (derializer != null) {
            return derializer;
        }

        if (clazz.isEnum()) {
            Class<?> deserClass = null;
            JSONType jsonType = clazz.getAnnotation(JSONType.class);
            if (jsonType != null) {
                deserClass = jsonType.deserializer();
                try {
                    /** 如果是枚舉類型並使用了註解,使用註解指定的反序列化 */
                    derializer = (ObjectDeserializer) deserClass.newInstance();
                    deserializers.put(clazz, derializer);
                    return derializer;
                } catch (Throwable error) {
                    // skip
                }
            }
            /** 如果是枚舉類型,使用EnumSerializer反序列化 */
            derializer = new EnumDeserializer(clazz);
        } else if (clazz.isArray()) {
            /** 如果是數組類型,使用數組對象反序列化實例 */
            derializer = ObjectArrayCodec.instance;
        } else if (clazz == Set.class || clazz == HashSet.class || clazz == Collection.class || clazz == List.class
                   || clazz == ArrayList.class) {
            /** 如果class實現集合接口,使用CollectionCodec反序列化 */
            derializer = CollectionCodec.instance;
        } else if (Collection.class.isAssignableFrom(clazz)) {
            /** 如果class實現類Collection接口,使用CollectionCodec反序列化 */
            derializer = CollectionCodec.instance;
        } else if (Map.class.isAssignableFrom(clazz)) {
            /** 如果class實現Map接口,使用MapDeserializer反序列化 */
            derializer = MapDeserializer.instance;
        } else if (Throwable.class.isAssignableFrom(clazz)) {
            /** 如果class繼承Throwable類,使用ThrowableDeserializer反序列化 */
            derializer = new ThrowableDeserializer(this, clazz);
        } else if (PropertyProcessable.class.isAssignableFrom(clazz)) {
            derializer = new PropertyProcessableDeserializer((Class<PropertyProcessable>)clazz);
        } else {
            /** 默認使用JavaBeanDeserializer反序列化(沒有開啓asm情況下) */
            derializer = createJavaBeanDeserializer(clazz, type);
        }

        /** 加入cache,避免同類型反覆創建 */
        putDeserializer(type, derializer);

        return derializer;
    }

其實查找反序列化和之前提到了序列化類似,根據特定類型匹配接口或者繼承實現類查找的,這裏指的關注一下創建通用反序列化實例 createJavaBeanDeserializer(clazz, type) :

    public ObjectDeserializer createJavaBeanDeserializer(Class<?> clazz, Type type) {
        boolean asmEnable = this.asmEnable & !this.fieldBased;

        /**
         *  ... 省略判定是否開啓asm邏輯
         */

        /** 創建通用Java對象反序列化實例JavaBeanDeserializer */
        if (!asmEnable) {
            return new JavaBeanDeserializer(this, clazz, type);
        }

        /**
         *  ... 省略創建基於asm的反序列化對象
         */
    }

對於自定義類反序列化,如果沒有開啓asm的情況下,會使用JavaBeanDeserializer進行反序列化轉換,這裏有意屏蔽基於asm直接操縱字節碼實現,後面會單獨列一個章節對該主題深入講解。

接下來會進入反序列化實現細節深入理解。

 

反序列化回調接口實現分析

內部註冊的反序列化

fastjson針對常用的類型已經註冊了反序列化實現方案,根據源代碼註冊com.alibaba.fastjson.parser.ParserConfig#initDeserializers可以得到列表:

通過上面表格發現幾乎把所有JDK常用的類型都註冊了一遍,目的是在運行時能夠查找到特定的反序列化實例而不需要使用默認Java的反序列化實例。

我們先從常見的類型開始分析反序列化實現。

 

1 BooleanCodec反序列化

    public <T> T deserialze(DefaultJSONParser parser, Type clazz, Object fieldName) {
        final JSONLexer lexer = parser.lexer;

        Boolean boolObj;

        try {
            /** 遇到true類型的token,預讀下一個token */
            if (lexer.token() == JSONToken.TRUE) {
                lexer.nextToken(JSONToken.COMMA);
                boolObj = Boolean.TRUE;
                /** 遇到false類型的token,預讀下一個token */
            } else if (lexer.token() == JSONToken.FALSE) {
                lexer.nextToken(JSONToken.COMMA);
                boolObj = Boolean.FALSE;
            } else if (lexer.token() == JSONToken.LITERAL_INT) {
                /** 遇到整數類型的token,預讀下一個token */
                int intValue = lexer.intValue();
                lexer.nextToken(JSONToken.COMMA);

                /** 1代表true,其他情況false */
                if (intValue == 1) {
                    boolObj = Boolean.TRUE;
                } else {
                    boolObj = Boolean.FALSE;
                }
            } else {
                Object value = parser.parse();

                if (value == null) {
                    return null;
                }

                /** 處理其他情況,比如Y,T代表true */
                boolObj = TypeUtils.castToBoolean(value);
            }
        } catch (Exception ex) {
            throw new JSONException("parseBoolean error, field : " + fieldName, ex);
        }

        /** 如果是原子類型 */
        if (clazz == AtomicBoolean.class) {
            return (T) new AtomicBoolean(boolObj.booleanValue());
        }

        return (T) boolObj;
    }

每次反序列化拿到token是,當前記錄的字符ch變量實際是token結尾的下一個字符,boolean類型字段會觸發該接口。

 

2 CharacterCodec反序列化

    public <T> T deserialze(DefaultJSONParser parser, Type clazz, Object fieldName) {
        /** 根據token解析類型 */
        Object value = parser.parse();
        return value == null
            ? null
            /** 轉換成char類型,如果是string取字符串第一個char */
            : (T) TypeUtils.castToChar(value);
    }

    public Object parse() {
        return parse(null);
    }

看着反序列化應該挺簡單,但是內部解析值委託給了DefaultJSONParser#parse(java.lang.Object), 會把字符串解析取第一個字符處理:

    public Object parse(Object fieldName) {
        final JSONLexer lexer = this.lexer;
        switch (lexer.token()) {
            /**
             *  ...忽略其他類型token,後面遇到會講解
             * /
            case LITERAL_STRING:
                /** 探測到是字符串類型,解析值 */
                String stringLiteral = lexer.stringVal();
                lexer.nextToken(JSONToken.COMMA);

                if (lexer.isEnabled(Feature.AllowISO8601DateFormat)) {
                    JSONScanner iso8601Lexer = new JSONScanner(stringLiteral);
                    try {
                        if (iso8601Lexer.scanISO8601DateIfMatch()) {
                            return iso8601Lexer.getCalendar().getTime();
                        }
                    } finally {
                        iso8601Lexer.close();
                    }
                }

                return stringLiteral;
            /**
             *  ...忽略其他類型token,後面遇到會講解
             * /
        }
    }

3 IntegerCodec反序列化

    public <T> T deserialze(DefaultJSONParser parser, Type clazz, Object fieldName) {
        final JSONLexer lexer = parser.lexer;

        final int token = lexer.token();

        /** 如果解析到null值,返回null */
        if (token == JSONToken.NULL) {
            lexer.nextToken(JSONToken.COMMA);
            return null;
        }


        Integer intObj;
        try {
            if (token == JSONToken.LITERAL_INT) {
                /** 整型字面量,預讀下一個token */
                int val = lexer.intValue();
                lexer.nextToken(JSONToken.COMMA);
                intObj = Integer.valueOf(val);
            } else if (token == JSONToken.LITERAL_FLOAT) {
                /** 浮點數字面量,預讀下一個token */
                BigDecimal decimalValue = lexer.decimalValue();
                lexer.nextToken(JSONToken.COMMA);
                intObj = Integer.valueOf(decimalValue.intValue());
            } else {
                if (token == JSONToken.LBRACE) {

                    /** 處理歷史原因反序列化AtomicInteger成map */
                    JSONObject jsonObject = new JSONObject(true);
                    parser.parseObject(jsonObject);
                    intObj = TypeUtils.castToInt(jsonObject);
                } else {
                    /** 處理其他情況 */
                    Object value = parser.parse();
                    intObj = TypeUtils.castToInt(value);
                }
            }
        } catch (Exception ex) {
            throw new JSONException("parseInt error, field : " + fieldName, ex);
        }


        if (clazz == AtomicInteger.class) {
            return (T) new AtomicInteger(intObj.intValue());
        }

        return (T) intObj;
    }

4 LongCodec反序列化

因爲和整數反序列化極其類似,請參考IntegerCodec不進行冗餘分析。

 

5 FloatCodec反序列化

    public static <T> T deserialze(DefaultJSONParser parser) {
        final JSONLexer lexer = parser.lexer;

        if (lexer.token() == JSONToken.LITERAL_INT) {
            /** 整型字面量,預讀下一個token */
            String val = lexer.numberString();
            lexer.nextToken(JSONToken.COMMA);
            return (T) Float.valueOf(Float.parseFloat(val));
        }

        if (lexer.token() == JSONToken.LITERAL_FLOAT) {
            /** 浮點數字面量,預讀下一個token */
            float val = lexer.floatValue();
            lexer.nextToken(JSONToken.COMMA);
            return (T) Float.valueOf(val);
        }

        /** 處理其他情況 */
        Object value = parser.parse();

        if (value == null) {
            return null;
        }

        return (T) TypeUtils.castToFloat(value);
    }

6  BigDecimalCodec反序列化

    public static <T> T deserialze(DefaultJSONParser parser) {
        final JSONLexer lexer = parser.lexer;
        if (lexer.token() == JSONToken.LITERAL_INT) {
            /** 整型字面量,預讀下一個token */
            BigDecimal decimalValue = lexer.decimalValue();
            lexer.nextToken(JSONToken.COMMA);
            return (T) decimalValue;
        }

        if (lexer.token() == JSONToken.LITERAL_FLOAT) {
            /** 浮點數字面量,預讀下一個token */
            BigDecimal val = lexer.decimalValue();
            lexer.nextToken(JSONToken.COMMA);
            return (T) val;
        }

        Object value = parser.parse();
        return value == null //
            ? null //
            : (T) TypeUtils.castToBigDecimal(value);
    }

 7 StringCodec反序列化

    public <T> T deserialze(DefaultJSONParser parser, Type clazz, Object fieldName) {
        if (clazz == StringBuffer.class) {
            /** 將解析的字符序列轉換成StringBuffer */
            final JSONLexer lexer = parser.lexer;
            if (lexer.token() == JSONToken.LITERAL_STRING) {
                /** 字符串字面量,預讀下一個token */
                String val = lexer.stringVal();
                lexer.nextToken(JSONToken.COMMA);

                return (T) new StringBuffer(val);
            }

            Object value = parser.parse();

            if (value == null) {
                return null;
            }

            return (T) new StringBuffer(value.toString());
        }

        if (clazz == StringBuilder.class) {
            /** 將解析的字符序列轉換成StringBuilder */
            final JSONLexer lexer = parser.lexer;
            if (lexer.token() == JSONToken.LITERAL_STRING) {
                String val = lexer.stringVal();
                /** 字符串字面量,預讀下一個token */
                lexer.nextToken(JSONToken.COMMA);

                return (T) new StringBuilder(val);
            }

            Object value = parser.parse();

            if (value == null) {
                return null;
            }

            return (T) new StringBuilder(value.toString());
        }

        return (T) deserialze(parser);
    }

    @SuppressWarnings("unchecked")
    public static <T> T deserialze(DefaultJSONParser parser) {
        final JSONLexer lexer = parser.getLexer();
        if (lexer.token() == JSONToken.LITERAL_STRING) {
            /** 字符串字面量,預讀下一個token */
            String val = lexer.stringVal();
            lexer.nextToken(JSONToken.COMMA);
            return (T) val;
        }

        if (lexer.token() == JSONToken.LITERAL_INT) {
            /** 整型字面量,預讀下一個token */
            String val = lexer.numberString();
            lexer.nextToken(JSONToken.COMMA);
            return (T) val;
        }

        Object value = parser.parse();

        if (value == null) {
            return null;
        }

        return (T) value.toString();
    }

8 ObjectArrayCodec反序列化

    public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
        final JSONLexer lexer = parser.lexer;
        int token = lexer.token();
        if (token == JSONToken.NULL) {
            /** 解析到Null,預讀下一個token */
            lexer.nextToken(JSONToken.COMMA);
            return null;
        }

        if (token == JSONToken.LITERAL_STRING || token == JSONToken.HEX) {
            byte[] bytes = lexer.bytesValue();
            lexer.nextToken(JSONToken.COMMA);

            if (bytes.length == 0 && type != byte[].class) {
                return null;
            }

            return (T) bytes;
        }

        Class componentClass;
        Type componentType;
        if (type instanceof GenericArrayType) {
            GenericArrayType clazz = (GenericArrayType) type;
            /** 獲取泛型數組真實參數類型 */
            componentType = clazz.getGenericComponentType();
            if (componentType instanceof TypeVariable) {
                TypeVariable typeVar = (TypeVariable) componentType;
                Type objType = parser.getContext().type;
                if (objType instanceof ParameterizedType) {
                    /** 獲取泛型參數化類型,eg: Collection<String> */
                    ParameterizedType objParamType = (ParameterizedType) objType;
                    Type objRawType = objParamType.getRawType();
                    Type actualType = null;
                    if (objRawType instanceof Class) {
                        /** 遍歷Class包含的參數化類型,查找與泛型數組類型名字一致的作爲真實類型 */
                        TypeVariable[] objTypeParams = ((Class) objRawType).getTypeParameters();
                        for (int i = 0; i < objTypeParams.length; ++i) {
                            if (objTypeParams[i].getName().equals(typeVar.getName())) {
                                actualType = objParamType.getActualTypeArguments()[i];
                            }
                        }
                    }
                    if (actualType instanceof Class) {
                        componentClass = (Class) actualType;
                    } else {
                        componentClass = Object.class;
                    }
                } else {
                    // 獲取數組類型上界
                    componentClass = TypeUtils.getClass(typeVar.getBounds()[0]);
                }
            } else {
                componentClass = TypeUtils.getClass(componentType);
            }
        } else {
            /** 非泛型數組,普通對象數組 */
            Class clazz = (Class) type;
            componentType = componentClass = clazz.getComponentType();
        }
        JSONArray array = new JSONArray();
        /** 根據token解析數組元素放到array中 */
        parser.parseArray(componentType, array, fieldName);

        return (T) toObjectArray(parser, componentClass, array);
    }

9 JavaBeanDeserializer反序列化

爲了節省冗餘的分析,我們主要分析最複雜的默認JavaBeanDeserializer反序列化實現。

   public JavaBeanDeserializer(ParserConfig config, JavaBeanInfo beanInfo){
        /** java對象類名稱 */
        this.clazz = beanInfo.clazz;
        this.beanInfo = beanInfo;

        Map<String, FieldDeserializer> alterNameFieldDeserializers = null;
        sortedFieldDeserializers = new FieldDeserializer[beanInfo.sortedFields.length];
        /**
         *  給已排序的字段創建反序列化實例,如果字段有別名,
         *  關聯別名到反序列化的映射
         */
        for (int i = 0, size = beanInfo.sortedFields.length; i < size; ++i) {
            FieldInfo fieldInfo = beanInfo.sortedFields[i];
            FieldDeserializer fieldDeserializer = config.createFieldDeserializer(config, beanInfo, fieldInfo);

            sortedFieldDeserializers[i] = fieldDeserializer;

            for (String name : fieldInfo.alternateNames) {
                if (alterNameFieldDeserializers == null) {
                    alterNameFieldDeserializers = new HashMap<String, FieldDeserializer>();
                }
                alterNameFieldDeserializers.put(name, fieldDeserializer);
            }
        }
        this.alterNameFieldDeserializers = alterNameFieldDeserializers;

        fieldDeserializers = new FieldDeserializer[beanInfo.fields.length];
        for (int i = 0, size = beanInfo.fields.length; i < size; ++i) {
            FieldInfo fieldInfo = beanInfo.fields[i];
            /** 採用二分法在sortedFieldDeserializers中查找已創建的反序列化類型 */
            FieldDeserializer fieldDeserializer = getFieldDeserializer(fieldInfo.name);
            fieldDeserializers[i] = fieldDeserializer;
        }
    }

構造函數就是簡單構造類字段對應的反序列化實例而已,接下來看下關鍵實現:

    protected <T> T deserialze(DefaultJSONParser parser,
                               Type type,
                               Object fieldName,
                               Object object,
                               int features,
                               int[] setFlags) {
        if (type == JSON.class || type == JSONObject.class) {
            /** 根據當前token類型判斷解析對象 */
            return (T) parser.parse();
        }

        final JSONLexerBase lexer = (JSONLexerBase) parser.lexer;
        final ParserConfig config = parser.getConfig();

        int token = lexer.token();
        if (token == JSONToken.NULL) {
            /** 解析null,預讀下一個token並返回 */
            lexer.nextToken(JSONToken.COMMA);
            return null;
        }

        ParseContext context = parser.getContext();
        if (object != null && context != null) {
            context = context.parent;
        }
        ParseContext childContext = null;

        try {
            Map<String, Object> fieldValues = null;

            if (token == JSONToken.RBRACE) {
                lexer.nextToken(JSONToken.COMMA);
                /** 遇到}認爲遇到對象結束,嘗試創建實例對象 */
                if (object == null) {
                    object = createInstance(parser, type);
                }
                return (T) object;
            }

            if (token == JSONToken.LBRACKET) {
                final int mask = Feature.SupportArrayToBean.mask;
                boolean isSupportArrayToBean = (beanInfo.parserFeatures & mask) != 0
                                               || lexer.isEnabled(Feature.SupportArrayToBean)
                                               || (features & mask) != 0
                                               ;
                if (isSupportArrayToBean) {
                    /** 將數組值反序列化爲對象,根據sortedFieldDeserializers依次寫字段值 */
                    return deserialzeArrayMapping(parser, type, fieldName, object);
                }
            }

            if (token != JSONToken.LBRACE && token != JSONToken.COMMA) {
                if (lexer.isBlankInput()) {
                    return null;
                }

                if (token == JSONToken.LITERAL_STRING) {
                    String strVal = lexer.stringVal();
                    /** 讀到空值字符串,返回null */
                    if (strVal.length() == 0) {
                        lexer.nextToken();
                        return null;
                    }

                    if (beanInfo.jsonType != null) {
                        /** 探測是否是枚舉類型 */
                        for (Class<?> seeAlsoClass : beanInfo.jsonType.seeAlso()) {
                            if (Enum.class.isAssignableFrom(seeAlsoClass)) {
                                try {
                                    Enum<?> e = Enum.valueOf((Class<Enum>) seeAlsoClass, strVal);
                                    return (T) e;
                                } catch (IllegalArgumentException e) {
                                    // skip
                                }
                            }
                        }
                    }
                } else if (token == JSONToken.LITERAL_ISO8601_DATE) {
                    Calendar calendar = lexer.getCalendar();
                }

                if (token == JSONToken.LBRACKET && lexer.getCurrent() == ']') {
                    /** 包含零元素的數組 */
                    lexer.next();
                    lexer.nextToken();
                    return null;
                }

                StringBuffer buf = (new StringBuffer()) //
                                                        .append("syntax error, expect {, actual ") //
                                                        .append(lexer.tokenName()) //
                                                        .append(", pos ") //
                                                        .append(lexer.pos());

                if (fieldName instanceof String) {
                    buf //
                        .append(", fieldName ") //
                        .append(fieldName);
                }

                buf.append(", fastjson-version ").append(JSON.VERSION);

                throw new JSONException(buf.toString());
            }

            if (parser.resolveStatus == DefaultJSONParser.TypeNameRedirect) {
                parser.resolveStatus = DefaultJSONParser.NONE;
            }

            String typeKey = beanInfo.typeKey;
            for (int fieldIndex = 0;; fieldIndex++) {
                String key = null;
                FieldDeserializer fieldDeser = null;
                FieldInfo fieldInfo = null;
                Class<?> fieldClass = null;
                JSONField feildAnnotation = null;
                /** 檢查是否所有字段都已經處理 */
                if (fieldIndex < sortedFieldDeserializers.length) {
                    fieldDeser = sortedFieldDeserializers[fieldIndex];
                    fieldInfo = fieldDeser.fieldInfo;
                    fieldClass = fieldInfo.fieldClass;
                    feildAnnotation = fieldInfo.getAnnotation();
                }

                boolean matchField = false;
                boolean valueParsed = false;

                Object fieldValue = null;
                if (fieldDeser != null) {
                    char[] name_chars = fieldInfo.name_chars;
                    if (fieldClass == int.class || fieldClass == Integer.class) {
                        /** 掃描整數值 */
                        fieldValue = lexer.scanFieldInt(name_chars);

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;  
                        }
                    } else if (fieldClass == long.class || fieldClass == Long.class) {
                        /** 掃描長整型值 */
                        fieldValue = lexer.scanFieldLong(name_chars);

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;  
                        }
                    } else if (fieldClass == String.class) {
                        /** 掃描字符串值 */
                        fieldValue = lexer.scanFieldString(name_chars);

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;  
                        }
                    } else if (fieldClass == java.util.Date.class && fieldInfo.format == null) {
                        /** 掃描日期值 */
                        fieldValue = lexer.scanFieldDate(name_chars);

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;
                        }
                    } else if (fieldClass == BigDecimal.class) {
                        /** 掃描高精度值 */
                        fieldValue = lexer.scanFieldDecimal(name_chars);

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;
                        }
                    } else if (fieldClass == BigInteger.class) {
                        fieldValue = lexer.scanFieldBigInteger(name_chars);

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;
                        }
                    } else if (fieldClass == boolean.class || fieldClass == Boolean.class) {
                        /** 掃描boolean值 */
                        fieldValue = lexer.scanFieldBoolean(name_chars);

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;  
                        }
                    } else if (fieldClass == float.class || fieldClass == Float.class) {
                        /** 掃描浮點值 */
                        fieldValue = lexer.scanFieldFloat(name_chars);

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;  
                        }
                    } else if (fieldClass == double.class || fieldClass == Double.class) {
                        /** 掃描double值 */
                        fieldValue = lexer.scanFieldDouble(name_chars);

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;  
                        }

                    } else if (fieldClass.isEnum()
                            && parser.getConfig().getDeserializer(fieldClass) instanceof EnumDeserializer
                            && (feildAnnotation == null || feildAnnotation.deserializeUsing() == Void.class)
                            ) {
                        if (fieldDeser instanceof DefaultFieldDeserializer) {
                            ObjectDeserializer fieldValueDeserilizer = ((DefaultFieldDeserializer) fieldDeser).fieldValueDeserilizer;
                            fieldValue = this.scanEnum(lexer, name_chars, fieldValueDeserilizer);

                            if (lexer.matchStat > 0) {
                                matchField = true;
                                valueParsed = true;
                            } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                                continue;
                            }
                        }
                    } else if (fieldClass == int[].class) {
                        /** 掃描整型數組值 */
                        fieldValue = lexer.scanFieldIntArray(name_chars);

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;
                        }
                    } else if (fieldClass == float[].class) {
                        fieldValue = lexer.scanFieldFloatArray(name_chars);

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;
                        }
                    } else if (fieldClass == float[][].class) {
                        /** 掃描浮點數組值 */
                        fieldValue = lexer.scanFieldFloatArray2(name_chars);

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;
                        }
                    } else if (lexer.matchField(name_chars)) {
                        matchField = true;
                    } else {
                        continue;
                    }
                }

                /** 如果當前字符串的json不匹配當前字段名稱 */
                if (!matchField) {
                    /** 將當前的字段名稱加入符號表 */
                    key = lexer.scanSymbol(parser.symbolTable);

                    /** 當前是無效的字段標識符,比如是,等符號 */
                    if (key == null) {
                        token = lexer.token();
                        if (token == JSONToken.RBRACE) {
                            /** 結束花括號, 預讀下一個token */
                            lexer.nextToken(JSONToken.COMMA);
                            break;
                        }
                        if (token == JSONToken.COMMA) {
                            if (lexer.isEnabled(Feature.AllowArbitraryCommas)) {
                                continue;
                            }
                        }
                    }

                    if ("$ref" == key && context != null) {
                        lexer.nextTokenWithColon(JSONToken.LITERAL_STRING);
                        token = lexer.token();
                        if (token == JSONToken.LITERAL_STRING) {
                            String ref = lexer.stringVal();
                            if ("@".equals(ref)) {
                                object = context.object;
                            } else if ("..".equals(ref)) {
                                ParseContext parentContext = context.parent;
                                if (parentContext.object != null) {
                                    object = parentContext.object;
                                } else {
                                    parser.addResolveTask(new ResolveTask(parentContext, ref));
                                    parser.resolveStatus = DefaultJSONParser.NeedToResolve;
                                }
                            } else if ("$".equals(ref)) {
                                ParseContext rootContext = context;
                                while (rootContext.parent != null) {
                                    rootContext = rootContext.parent;
                                }

                                if (rootContext.object != null) {
                                    object = rootContext.object;
                                } else {
                                    parser.addResolveTask(new ResolveTask(rootContext, ref));
                                    parser.resolveStatus = DefaultJSONParser.NeedToResolve;
                                }
                            } else {
                                Object refObj = parser.resolveReference(ref);
                                if (refObj != null) {
                                    object = refObj;
                                } else {
                                    parser.addResolveTask(new ResolveTask(context, ref));
                                    parser.resolveStatus = DefaultJSONParser.NeedToResolve;
                                }
                            }
                        } else {
                            throw new JSONException("illegal ref, " + JSONToken.name(token));
                        }

                        lexer.nextToken(JSONToken.RBRACE);
                        if (lexer.token() != JSONToken.RBRACE) {
                            throw new JSONException("illegal ref");
                        }
                        lexer.nextToken(JSONToken.COMMA);

                        parser.setContext(context, object, fieldName);

                        return (T) object;
                    }

                    if ((typeKey != null && typeKey.equals(key))
                            || JSON.DEFAULT_TYPE_KEY == key) {
                        lexer.nextTokenWithColon(JSONToken.LITERAL_STRING);
                        if (lexer.token() == JSONToken.LITERAL_STRING) {
                            String typeName = lexer.stringVal();
                            lexer.nextToken(JSONToken.COMMA);

                            /** 忽略字符串中包含@type解析 */
                            if (typeName.equals(beanInfo.typeName)|| parser.isEnabled(Feature.IgnoreAutoType)) {
                                if (lexer.token() == JSONToken.RBRACE) {
                                    lexer.nextToken();
                                    break;
                                }
                                continue;
                            }


                            /** 根據枚舉seeAlso查找反序列化實例 */
                            ObjectDeserializer deserializer = getSeeAlso(config, this.beanInfo, typeName);
                            Class<?> userType = null;

                            if (deserializer == null) {
                                /** 無法匹配,查找類對應的泛型或者參數化類型關聯的反序列化實例 */
                                Class<?> expectClass = TypeUtils.getClass(type);
                                userType = config.checkAutoType(typeName, expectClass, lexer.getFeatures());
                                deserializer = parser.getConfig().getDeserializer(userType);
                            }

                            Object typedObject = deserializer.deserialze(parser, userType, fieldName);
                            if (deserializer instanceof JavaBeanDeserializer) {
                                JavaBeanDeserializer javaBeanDeserializer = (JavaBeanDeserializer) deserializer;
                                if (typeKey != null) {
                                    FieldDeserializer typeKeyFieldDeser = javaBeanDeserializer.getFieldDeserializer(typeKey);
                                    typeKeyFieldDeser.setValue(typedObject, typeName);
                                }
                            }
                            return (T) typedObject;
                        } else {
                            throw new JSONException("syntax error");
                        }
                    }
                }

                /** 第一次創建並初始化對象實例 */
                if (object == null && fieldValues == null) {
                    object = createInstance(parser, type);
                    if (object == null) {
                        fieldValues = new HashMap<String, Object>(this.fieldDeserializers.length);
                    }
                    childContext = parser.setContext(context, object, fieldName);
                    if (setFlags == null) {
                        setFlags = new int[(this.fieldDeserializers.length / 32) + 1];
                    }
                }

                if (matchField) {
                    if (!valueParsed) {
                        /** json串當前滿足字段名稱,並且沒有解析過值 ,
                         *  直接使用當前字段關聯的反序列化實例解析
                         */
                        fieldDeser.parseField(parser, object, type, fieldValues);
                    } else {
                        if (object == null) {
                            /** 值已經解析過了,存儲到map中 */
                            fieldValues.put(fieldInfo.name, fieldValue);
                        } else if (fieldValue == null) {
                            /** 字段值是null,排除int,long,float,double,boolean */
                            if (fieldClass != int.class
                                    && fieldClass != long.class
                                    && fieldClass != float.class
                                    && fieldClass != double.class
                                    && fieldClass != boolean.class
                                    ) {
                                fieldDeser.setValue(object, fieldValue);
                            }
                        } else {
                            fieldDeser.setValue(object, fieldValue);
                        }

                        if (setFlags != null) {
                            int flagIndex = fieldIndex / 32;
                            int bitIndex = fieldIndex % 32;
                            setFlags[flagIndex] |= (1 >> bitIndex);
                        }

                        if (lexer.matchStat == JSONLexer.END) {
                            break;
                        }
                    }
                } else {
                    /** 字段名稱當前和json串不匹配,通常順序或者字段增加或者缺少,
                     *  根據key查找反序列化實例解析
                     */
                    boolean match = parseField(parser, key, object, type, fieldValues, setFlags);
                    if (!match) {
                        /** 遇到封閉花括號,與讀下一個token,跳出循環 */
                        if (lexer.token() == JSONToken.RBRACE) {
                            lexer.nextToken();
                            break;
                        }

                        continue;
                    } else if (lexer.token() == JSONToken.COLON) {
                        throw new JSONException("syntax error, unexpect token ':'");
                    }
                }

                if (lexer.token() == JSONToken.COMMA) {
                    continue;
                }

                if (lexer.token() == JSONToken.RBRACE) {
                    lexer.nextToken(JSONToken.COMMA);
                    break;
                }

                if (lexer.token() == JSONToken.IDENTIFIER || lexer.token() == JSONToken.ERROR) {
                    throw new JSONException("syntax error, unexpect token " + JSONToken.name(lexer.token()));
                }
            }

            if (object == null) {
                if (fieldValues == null) {
                    /** 第一次創建並初始化對象實例 */
                    object = createInstance(parser, type);
                    if (childContext == null) {
                        childContext = parser.setContext(context, object, fieldName);
                    }
                    return (T) object;
                }

                /** 提取構造函數參數名稱 */
                String[] paramNames = beanInfo.creatorConstructorParameters;
                final Object[] params;
                if (paramNames != null) {
                    params = new Object[paramNames.length];
                    for (int i = 0; i < paramNames.length; i++) {
                        String paramName = paramNames[i];

                        Object param = fieldValues.remove(paramName);
                        /** 解析過的字段不包含當前參數名字 */
                        if (param == null) {
                            Type fieldType = beanInfo.creatorConstructorParameterTypes[i];
                            FieldInfo fieldInfo = beanInfo.fields[i];
                            /** 探測並設置類型默認值 */
                            if (fieldType == byte.class) {
                                param = (byte) 0;
                            } else if (fieldType == short.class) {
                                param = (short) 0;
                            } else if (fieldType == int.class) {
                                param = 0;
                            } else if (fieldType == long.class) {
                                param = 0L;
                            } else if (fieldType == float.class) {
                                param = 0F;
                            } else if (fieldType == double.class) {
                                param = 0D;
                            } else if (fieldType == boolean.class) {
                                param = Boolean.FALSE;
                            } else if (fieldType == String.class
                                    && (fieldInfo.parserFeatures & Feature.InitStringFieldAsEmpty.mask) != 0) {
                                param = "";
                            }
                        }
                        params[i] = param;
                    }
                } else {
                    /** 根據字段探測並初始化構造函數參數默認值 */
                    FieldInfo[] fieldInfoList = beanInfo.fields;
                    int size = fieldInfoList.length;
                    params = new Object[size];
                    for (int i = 0; i < size; ++i) {
                        FieldInfo fieldInfo = fieldInfoList[i];
                        Object param = fieldValues.get(fieldInfo.name);
                        if (param == null) {
                            Type fieldType = fieldInfo.fieldType;
                            if (fieldType == byte.class) {
                                param = (byte) 0;
                            } else if (fieldType == short.class) {
                                param = (short) 0;
                            } else if (fieldType == int.class) {
                                param = 0;
                            } else if (fieldType == long.class) {
                                param = 0L;
                            } else if (fieldType == float.class) {
                                param = 0F;
                            } else if (fieldType == double.class) {
                                param = 0D;
                            } else if (fieldType == boolean.class) {
                                param = Boolean.FALSE;
                            } else if (fieldType == String.class
                                    && (fieldInfo.parserFeatures & Feature.InitStringFieldAsEmpty.mask) != 0) {
                                param = "";
                            }
                        }
                        params[i] = param;
                    }
                }

                if (beanInfo.creatorConstructor != null) {
                    try {
                        object = beanInfo.creatorConstructor.newInstance(params);
                    } catch (Exception e) {
                        throw new JSONException("create instance error, " + paramNames + ", "
                                                + beanInfo.creatorConstructor.toGenericString(), e);
                    }

                    if (paramNames != null) {
                        /** 剩餘字段查找反序列化器set值 */
                        for (Map.Entry<String, Object> entry : fieldValues.entrySet()) {
                            FieldDeserializer fieldDeserializer = getFieldDeserializer(entry.getKey());
                            if (fieldDeserializer != null) {
                                fieldDeserializer.setValue(object, entry.getValue());
                            }
                        }
                    }
                } else if (beanInfo.factoryMethod != null) {
                    try {
                        object = beanInfo.factoryMethod.invoke(null, params);
                    } catch (Exception e) {
                        throw new JSONException("create factory method error, " + beanInfo.factoryMethod.toString(), e);
                    }
                }

                childContext.object = object;
            }

            /** 檢查是否擴展後置方法buildMethod,如果有進行調用 */
            Method buildMethod = beanInfo.buildMethod;
            if (buildMethod == null) {
                return (T) object;
            }


            Object builtObj;
            try {
                builtObj = buildMethod.invoke(object);
            } catch (Exception e) {
                throw new JSONException("build object error", e);
            }

            return (T) builtObj;
        } finally {
            if (childContext != null) {
                childContext.object = object;
            }
            parser.setContext(context);
        }
    }

 

這段代碼實在又臭又長,實際做的事情如下:

1  根據類所有的字段,字段類型進行json串進行匹配,首先檢查json串的值是否和當前字段名稱相等,如果相等認爲匹配成功,會創建實例對象並且把解析字段值set進去。
2  如果當前json串順序和java對象字段不一致怎麼辦,這個時候我字段又全部遍歷完了,fastjson會自動把當前解析的字段名稱加入符號表中,然後查找字段名稱對應的反序列化實例進行set值操作
3  當前實現提供瞭解析對象後buildMethod擴展點,如果提供了會進行回調然後返回


值得一提的是構造函數處理:

    public Object createInstance(DefaultJSONParser parser, Type type) {
        if (type instanceof Class) {
            if (clazz.isInterface()) {
                /** 針對反序列化時接口類型的,通過jdk冬天代理攔截put和get等操作,
                 *  進行set或者put值的操作值會存儲在jsonobject內部的map結構
                 */
                Class<?> clazz = (Class<?>) type;
                ClassLoader loader = Thread.currentThread().getContextClassLoader();
                final JSONObject obj = new JSONObject();
                Object proxy = Proxy.newProxyInstance(loader, new Class<?>[] { clazz }, obj);
                return proxy;
            }
        }

        /** 忽略沒有默認構造函數和沒有創建對象的工廠方法 */
        if (beanInfo.defaultConstructor == null && beanInfo.factoryMethod == null) {
            return null;
        }

        /** 忽略同時存在顯示構造函數和創建對象的工廠方法的場景 */
        if (beanInfo.factoryMethod != null && beanInfo.defaultConstructorParameterSize > 0) {
            return null;
        }

        Object object;
        try {
            Constructor<?> constructor = beanInfo.defaultConstructor;
            /** 存在默認無參構造函數 */
            if (beanInfo.defaultConstructorParameterSize == 0) {
                if (constructor != null) {
                    object = constructor.newInstance();
                } else {
                    /** 否則使用工廠方法生成對象 */
                    object = beanInfo.factoryMethod.invoke(null);
                }
            } else {
                ParseContext context = parser.getContext();
                if (context == null || context.object == null) {
                    throw new JSONException("can't create non-static inner class instance.");
                }

                final String typeName;
                if (type instanceof Class) {
                    typeName = ((Class<?>) type).getName();
                } else {
                    throw new JSONException("can't create non-static inner class instance.");
                }

                final int lastIndex = typeName.lastIndexOf('$');
                String parentClassName = typeName.substring(0, lastIndex);

                Object ctxObj = context.object;
                String parentName = ctxObj.getClass().getName();

                Object param = null;
                if (!parentName.equals(parentClassName)) {
                    /** 處理繼承過來的類 */
                    ParseContext parentContext = context.parent;
                    if (parentContext != null
                            && parentContext.object != null
                            && ("java.util.ArrayList".equals(parentName)
                            || "java.util.List".equals(parentName)
                            || "java.util.Collection".equals(parentName)
                            || "java.util.Map".equals(parentName)
                            || "java.util.HashMap".equals(parentName))) {
                        parentName = parentContext.object.getClass().getName();
                        if (parentName.equals(parentClassName)) {
                            param = parentContext.object;
                        }
                    }
                } else {
                    /** 處理非靜態內部類場景,
                     *  編譯器會自動修改內部類構造函數,添加外層類實例對象作爲參數,
                     *  ctxObj就是外層實例對象
                     */
                    param = ctxObj;
                }

                if (param == null) {
                    throw new JSONException("can't create non-static inner class instance.");
                }

                object = constructor.newInstance(param);
            }
        } catch (JSONException e) {
            throw e;
        } catch (Exception e) {
            throw new JSONException("create instance error, class " + clazz.getName(), e);
        }

        /** 開啓InitStringFieldAsEmpty特性,會把字符串字段初始化爲空串 */
        if (parser != null
                && parser.lexer.isEnabled(Feature.InitStringFieldAsEmpty)) {
            for (FieldInfo fieldInfo : beanInfo.fields) {
                if (fieldInfo.fieldClass == String.class) {
                    try {
                        fieldInfo.set(object, "");
                    } catch (Exception e) {
                        throw new JSONException("create instance error, class " + clazz.getName(), e);
                    }
                }
            }
        }

        return object;
    }

編譯器會爲非靜態內部類構造函數添加外層的實例對象作爲第一個參數,所以在生成實例化對象的時候會從上下文中獲取外層對象進行反射創建對象constructor.newInstance(param)

爲了更容易理解這段邏輯,提供一下單元測試可以調試:

 

com.alibaba.json.bvt.parser.deser.InnerClassDeser2#test_for_inner_class

com.alibaba.json.bvt.parser.deser.InnerClassDeser3#test_for_inner_class

com.alibaba.json.bvt.parser.deser.InnerClassDeser4#test_for_inner_class

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章