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-bitsfor (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 charsbuf[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 intint 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)) {// awtif (!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}}}// jdk8if ((!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) {// skipjdk8Error = 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) {// skiporacleJdbcError = 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) {// skipspringfoxError = 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) {// skipguavaError = 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) {// skipjsonnullError = 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-matchedbreak;}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.jsonTypeif (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) {// skipawtError = 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) {// skipjdk8Error = 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_classcom.alibaba.json.bvt.parser.deser.InnerClassDeser3#test_for_inner_classcom.alibaba.json.bvt.parser.deser.InnerClassDeser4#test_for_inner_class

com.alibaba.fastjson 序列化 反序列相关推荐

  1. Alibaba fastjson 序列化与反序列化

    fastjson在官网的定义号称最小最快 多态的json序列化工具.fastjson采用独创的算法,将parse的速度提升到极致,超过所有json库,包括曾经号称最快的jackson.并且还超越了go ...

  2. Fastjson 序列化,反序列化Map对象排序问题(字符串转map,map转字符串)

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qingfeng812/article/details/61194594 背景 记录项目中遇到的 关于 ...

  3. alibaba Fastjson的JOSN解析库 -

    JSON,全称:JavaScript Object Notation,作为一个常见的轻量级的数据交换格式,应该在一个程序员的开发生涯中是常接触的.简洁和清晰的层次结构使得 JSON 成为理想的数据交换 ...

  4. ClassCastException: java.lang.String cannot be cast to com.alibaba.fastjson.JSONObject 的解决办法

    问题概述 关于这个问题,是与第三方公司合作,远程调用服务接口时(就相当于调用远程服务提供者)遇到的这个问题," java.lang.ClassCastException: java.lang ...

  5. com.alibaba.fastjson.JSONObject循环给同一对象赋值会出现$ref:$[0]现象问题

    1.今天定义了一个JSONObject对象,引用的com.alibaba.fastjson.JSONObject,循环给这个对象赋值出现"$ref":"$[0]" ...

  6. Java基础/利用fastjson序列化对象为JSON

    利用fastjson序列化对象为JSON 参考博客:http://blog.csdn.net/zeuskingzb/article/details/17468079 Step1:定义实体类 //用户类 ...

  7. 【Android Protobuf 序列化】Protobuf 性能测试 ( fastjson 序列化与反序列化 | gson 序列化与反序列化 | 三种序列化与反序列化性能对比 )

    文章目录 一.导入依赖库 二.构造 JavaBean 三.fastjson 序列化与反序列化 四.gson 序列化与反序列化 五.完整代码 1.主界面代码 2.JSON 测试代码 3.执行结果 六.参 ...

  8. fastjson序列化原理详解

    2019独角兽企业重金招聘Python工程师标准>>> 所有序列化的API都在JSON类中,方法名称为toJSONString,或者我们也可以设计自己的序列化方法,代码如下: pub ...

  9. 解决com.alibaba.fastjson.JSONException: autoType is not support

    转载自 https://blog.csdn.net/cdyjy_litao/article/details/72458538 最近发现进程运行日志中出现很多下面的日志: com.alibaba.fas ...

最新文章

  1. Halide应用开发
  2. java ee webservice_javaEE调用webservice总结【利用WSDL】(转载)
  3. CV领域论文常用单词汇总
  4. MaxCompute Tunnel SDK数据上传利器——BufferedWriter使用指南
  5. Spring-AOP @AspectJ切点函数之execution()
  6. ActiveMQ点对点消息通信demo
  7. C/C++语言中字符串多行书写方法
  8. PHP常用的自定义函数
  9. linux tlhelp32.h,CreateToolhelp32Snapshot
  10. Java中文编码转换与字节长度判断
  11. devc 能优化吗_小网站能做seo优化吗?如何为小公司网站做seo优化?
  12. java 做窗体_java怎么做窗体
  13. mysql锘縖_根据中文字符串查询拼音声母
  14. 生物什么时候学公式计算机,高考生物重要规律性关系及公式精华归纳,转走吧...
  15. matlab制作扇形统计图及颜色调配
  16. WIN10桌面图标变成白文件的一种解决方法
  17. 微信小程序 java springboot理发店美容店预约系统
  18. linux如何脚本监控tps,对Linux进行详细的性能监控的方法
  19. 一个女程序员眼中的程序员
  20. 如何制作毕业地图分布图_如何绘制127个特色小镇地图分布地图

热门文章

  1. 未来最高明的数据恢复师
  2. iOS iphonex底部安全区域
  3. 【photoshop Action Manager】设置矩形选框工具样式固定比例
  4. Android全选反选
  5. 达人评测 骁龙888plus和骁龙888参数对比选哪个好
  6. 学习开发没有捷径,也几乎不存在带路会学的快一些的情况
  7. Termux设置mysql/nginx/php等服务随软件自启动
  8. Git(仓库,分支,生成SSH公钥,IDEA集成Git)
  9. Tensorboard 启动失败问题解决
  10. 3D MAX 动画制作教程