概要 fastjson核心功能包括序列化和反序列化,序列化的含义是将java对象转换成跨语言的json字符串。我认为从这里作为分析入口相对比较简单,第二章会从反序列化角度切入,会包含词法分析等较为复杂点展开。
现在,我们正式开始咀嚼原汁原味的代码吧,我添加了详细的代码注释。
SerializeWriter成员变量 com.alibaba.fastjson.serializer.SerializeWriter
类非常重要,序列化输出都是通过转换底层操作,重要字段如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 private final static ThreadLocal<char []> bufLocal = new ThreadLocal<char []>();private final static ThreadLocal<byte []> bytesBufLocal = new ThreadLocal<byte []>();protected char buf[];protected int count;protected int features;private final Writer writer;protected boolean useSingleQuotes;protected boolean quoteFieldNames;protected boolean sortField;protected boolean disableCircularReferenceDetect;protected boolean beanToArray;protected boolean writeNonStringValueAsString;protected boolean notWriteDefaultValue;protected boolean writeEnumUsingName;protected boolean writeEnumUsingToString;protected boolean writeDirect;protected char keySeperator;protected int maxBufSize = -1 ;protected boolean browserSecure;protected long sepcialBits;
SerializeWriter成员函数 序列化整形数字 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 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 ) { expandCapacity(newcount); } else { char [] chars = new char [size]; IOUtils.getChars(i, size, chars); write(chars, 0 , chars.length); return ; } } IOUtils.getChars(i, newcount, buf); 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), 但是精度更高。
序列化长整形数字 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 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 ) { expandCapacity(newcount); } else { char [] chars = new char [size]; 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转换为单字符同样的技巧。
序列化浮点类型数字 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 public void writeDouble (double doubleValue, boolean checkWriteClassName) { if (Double.isNaN(doubleValue) || Double.isInfinite(doubleValue)) { writeNull(); } else { String doubleText = Double.toString(doubleValue); if (isEnabled(SerializerFeature.WriteNullNumberAsZero) && doubleText.endsWith(".0" )) { doubleText = doubleText.substring(0 , doubleText.length() - 2 ); } write(doubleText); if (checkWriteClassName && isEnabled(SerializerFeature.WriteClassName)) { write('D' ); } } } public void writeFloat (float value, boolean checkWriteClassName) { if (Float.isNaN(value) || Float.isInfinite(value)) { writeNull(); } else { String floatText= Float.toString(value); if (isEnabled(SerializerFeature.WriteNullNumberAsZero) && floatText.endsWith(".0" )) { floatText = floatText.substring(0 , floatText.length() - 2 ); } write(floatText); if (checkWriteClassName && isEnabled(SerializerFeature.WriteClassName)) { write('F' ); } } }
序列化浮点类型的基本思路是先转换为字符串,然后在输出到输出流中。
序列化枚举类型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public void writeEnum (Enum<?> value) { if (value == null ) { writeNull(); return ; } String strVal = null ; if (writeEnumUsingName && !writeEnumUsingToString) { strVal = value.name(); } else if (writeEnumUsingToString) { strVal = value.toString();; } if (strVal != null ) { char quote = isEnabled(SerializerFeature.UseSingleQuotes) ? '\'' : '"' ; write(quote); write(strVal); write(quote); } else { writeInt(value.ordinal()); } }
序列化单字符 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public void write (int c) { int newcount = count + 1 ; if (newcount > buf.length) { if (writer == null ) { expandCapacity(newcount); } else { flush(); newcount = 1 ; } } buf[count] = (char ) c; count = newcount; }
序列化Null 1 2 3 4 public void writeNull () { write("null" ); }
序列化Boolean 1 2 3 4 5 6 7 8 9 public void write (boolean value) { if (value) { write("true" ); } else { write("false" ); } }