1. 程式人生 > >fastjson深度原始碼解析- 序列化(五)

fastjson深度原始碼解析- 序列化(五)

序列化回撥介面實現分析

內部註冊的序列化

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

註冊的型別 序列化例項 是否支援序列化 是否支援反序列化
Boolean BooleanCodec
Character CharacterCodec
Byte IntegerCodec
Short IntegerCodec
Integer IntegerCodec
Long LongCodec
Float FloatCodec
Double DoubleSerializer -
BigDecimal BigDecimalCodec
BigInteger BigIntegerCodec
String StringCodec
byte[] PrimitiveArraySerializer -
short[] PrimitiveArraySerializer -
int[] PrimitiveArraySerializer -
long[] PrimitiveArraySerializer -
float[] PrimitiveArraySerializer -
double[] PrimitiveArraySerializer -
boolean[] PrimitiveArraySerializer -
char[] PrimitiveArraySerializer -
Object[] ObjectArrayCodec
Class MiscCodec
SimpleDateFormat MiscCodec
Currency MiscCodec
TimeZone MiscCodec
InetAddress MiscCodec
Inet4Address MiscCodec
Inet6Address MiscCodec
InetSocketAddress MiscCodec
File MiscCodec
Appendable AppendableSerializer -
StringBuffer AppendableSerializer -
StringBuilder AppendableSerializer -
Charset ToStringSerializer -
Pattern ToStringSerializer -
Locale ToStringSerializer -
URI ToStringSerializer -
URL ToStringSerializer -
UUID ToStringSerializer -
AtomicBoolean AtomicCodec
AtomicInteger AtomicCodec
AtomicLong AtomicCodec
AtomicReference ReferenceCodec
AtomicIntegerArray AtomicCodec
AtomicLongArray AtomicCodec
WeakReference ReferenceCodec
SoftReference ReferenceCodec
LinkedList CollectionCodec

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字面量值。

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

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

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字元。

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

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('.');
            }
        }
    }

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

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

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

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型別查詢具體的序列化器輸出,這裡優化了如果元素相同的元素避免冗餘的查詢序列化器。

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輸出,極大地降低了輸出位元組大小。

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

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

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(']');
    }

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

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