fastJson序列化和反序列化流程
一、核心源碼
1、SerializeWriter
該類主要用於序列化,有以下成員變量
public final class SerializeWriter extends Writer {
/**
* 儲存序列化結果的字段
*/
protected char buf[];
/**
* 寫入緩存的長度
*/
protected int count;
/**
* 該對象用於close時將buf綁定到線程上,避免下次重複new出
*/
private final static ThreadLocal<SoftReference<char[]>> bufLocal = new ThreadLocal<SoftReference<char[]>>();
/**
* 序列化的一些特性配置
*/
private int features;
/**
* 包裝對象,支持對Writer類型包含數據的序列化
*/
private final Writer writer;
//傳入Writer對象
public SerializeWriter(Writer writer){
this.writer = writer;
//默認序列化屬性
this.features = JSON.DEFAULT_GENERATE_FEATURE;
//獲取線程緩存buf對象
SoftReference<char[]> ref = bufLocal.get();
//獲取到賦值給當前buf並清空,防止重複new出。
//由於count在關閉的時候已經等於0,所以即使buf裏有數據,也不會影響當次結果
if (ref != null) {
buf = ref.get();
bufLocal.set(null);
}
if (buf == null) {
buf = new char[1024];
}
}
}
存在buf的緩存對象,自然需要具體的寫入方法。下圖列出了主要的寫入方法
類的方法結構圖
接下來我們來看默認的配置特性
JSON.DEFAULT_GENERATE_FEATURE
public abstract class JSON implements JSONStreamAware, JSONAware {
public static int DEFAULT_GENERATE_FEATURE;
static {
int features = 0;
//輸出key時使用雙引號
features |= SerializerFeature.QuoteFieldNames.getMask();
//跳過Transient註解的字段
features |= SerializerFeature.SkipTransientField.getMask();
//將Enum枚舉轉換爲toString()字符串
features |= SerializerFeature.WriteEnumUsingToString.getMask();
//按字段名稱排序後輸出
features |= SerializerFeature.SortField.getMask();
// features |=
// com.alibaba.fastjson.serializer.SerializerFeature.WriteSlashAsSpecial.getMask();
DEFAULT_GENERATE_FEATURE = features;
}
}
二、序列化
1.序列化過程
我們從調用方法toJSONString開始,會調用
public static final String toJSONString(Object object, SerializerFeature... features) {
//詳細寫數據的類,存儲序列化過程的數據,最後通過 out.toString()轉化爲json字符串
SerializeWriter out = new SerializeWriter();
try {
//Json序列化解析對象的類,解析過程中向out寫入數據
JSONSerializer serializer = new JSONSerializer(out);
//向解析器添加序列化屬性
for (com.alibaba.fastjson.serializer.SerializerFeature feature : features) {
serializer.config(feature, true);
}
//解析傳入的對象,保存在out中
serializer.write(object);
//將解析的結果轉成String輸出
return out.toString();
} finally {
out.close();
}
}
接下里我們來看JSONSerializer的write方法
public class JSONSerializer {
……
public final void write(Object object) {
//如果空對象,直接寫入null字符串
if (object == null) {
out.writeNull();
return;
}
//獲取到類,通過getObjectWriter(clazz)找到對應的解析器
Class<?> clazz = object.getClass();
ObjectSerializer writer = getObjectWriter(clazz);
try {
//對應序列化器執行序列化寫操作
writer.write(this, object, null, null);
} catch (IOException e) {
throw new JSONException(e.getMessage(), e);
}
}
……
}
那我們來看看怎麼獲取對應序列化器的
public ObjectSerializer getObjectWriter(Class<?> clazz) {
//先從SerializeConfig配置中獲取默認基礎類型的代碼序列化器
ObjectSerializer writer = config.get(clazz);
//如果未獲取到,再解析對象類型,並加入配置列表當中,例如
if (writer == null) {
if (Map.class.isAssignableFrom(clazz)) {
//Map類型
config.put(clazz, MapSerializer.instance);
} else if (List.class.isAssignableFrom(clazz)) {
//List類型
config.put(clazz, ListSerializer.instance);
} else if (Collection.class.isAssignableFrom(clazz)) {
//Collection類型
config.put(clazz, CollectionSerializer.instance);
} else if (Date.class.isAssignableFrom(clazz)) {
//Date日期類型
config.put(clazz, DateSerializer.instance);
} else if (JSONAware.class.isAssignableFrom(clazz)) {
//JSONAware日期類型
config.put(clazz, JSONAwareSerializer.instance);
} else if (JSONSerializable.class.isAssignableFrom(clazz)) {
//JSONSerializable日期類型
config.put(clazz, JSONSerializableSerializer.instance);
} else if (JSONStreamAware.class.isAssignableFrom(clazz)) {
//JSONStreamAware類型
config.put(clazz, JSONStreamAwareSerializer.instance);
} else if (clazz.isEnum() || (clazz.getSuperclass() != null && clazz.getSuperclass().isEnum())) {
//枚舉類型的類
config.put(clazz, EnumSerializer.instance);
} else if (clazz.isArray()) {
//數組類型
Class<?> componentType = clazz.getComponentType();
ObjectSerializer compObjectSerializer = getObjectWriter(componentType);
config.put(clazz, new ArraySerializer(componentType, compObjectSerializer));
} else if (Throwable.class.isAssignableFrom(clazz)) {
//異常類型
config.put(clazz, new ExceptionSerializer(clazz));
} else if (TimeZone.class.isAssignableFrom(clazz)) {
//市區類型
config.put(clazz, TimeZoneCodec.instance);
} else if (Charset.class.isAssignableFrom(clazz)) {
//字符編碼類型
config.put(clazz, CharsetCodec.instance);
} else if (Enumeration.class.isAssignableFrom(clazz)) {
//實現了枚舉接口的類
config.put(clazz, EnumerationSeriliazer.instance);
} else if (Calendar.class.isAssignableFrom(clazz)) {
//日曆類型
config.put(clazz, CalendarCodec.instance);
} else {
boolean isCglibProxy = false;
boolean isJavassistProxy = false;
//判斷是否是CGLIB或javassist生成的代理類
for (Class<?> item : clazz.getInterfaces()) {
if (item.getName().equals("net.sf.cglib.proxy.Factory")
|| item.getName().equals("org.springframework.cglib.proxy.Factory")) {
isCglibProxy = true;
break;
} else if (item.getName().equals("javassist.util.proxy.ProxyObject")) {
isJavassistProxy = true;
break;
}
}
//如果是CGLIB或javassist生成的代理類,就放父類的序列化器
if (isCglibProxy || isJavassistProxy) {
Class<?> superClazz = clazz.getSuperclass();
ObjectSerializer superWriter = getObjectWriter(superClazz);
config.put(clazz, superWriter);
return superWriter;
}
//不管是不是動態代理類型,都是用JavaBean序列化器
if (Proxy.isProxyClass(clazz)) {
config.put(clazz, config.createJavaBeanSerializer(clazz));
} else {
config.put(clazz, config.createJavaBeanSerializer(clazz));
}
}
//上面向config中添加了類對應的序列化器,現在獲取Writer返回
writer = config.get(clazz);
}
return writer;
}
回過來看看第一行的默認配置的基礎解析器
public class SerializeConfig extends IdentityHashMap<Type, ObjectSerializer> {
……
public SerializeConfig(int tableSize){
super(tableSize);
put(Boolean.class, BooleanCodec.instance);
put(Character.class, CharacterCodec.instance);
put(Byte.class, IntegerCodec.instance);
put(Short.class, IntegerCodec.instance);
put(Integer.class, IntegerCodec.instance);
put(Long.class, LongCodec.instance);
put(Float.class, FloatCodec.instance);
put(Double.class, DoubleSerializer.instance);
put(BigDecimal.class, BigDecimalCodec.instance);
put(BigInteger.class, BigIntegerCodec.instance);
put(String.class, StringCodec.instance);
put(byte[].class, ByteArraySerializer.instance);
put(short[].class, ShortArraySerializer.instance);
put(int[].class, IntArraySerializer.instance);
put(long[].class, LongArraySerializer.instance);
put(float[].class, FloatArraySerializer.instance);
put(double[].class, DoubleArraySerializer.instance);
put(boolean[].class, BooleanArraySerializer.instance);
put(char[].class, CharArraySerializer.instance);
put(Object[].class, ObjectArraySerializer.instance);
put(Class.class, ClassSerializer.instance);
put(SimpleDateFormat.class, DateFormatSerializer.instance);
put(Locale.class, LocaleCodec.instance);
put(Currency.class, CurrencyCodec.instance);
put(TimeZone.class, TimeZoneCodec.instance);
put(UUID.class, UUIDCodec.instance);
put(InetAddress.class, InetAddressCodec.instance);
put(Inet4Address.class, InetAddressCodec.instance);
put(Inet6Address.class, InetAddressCodec.instance);
put(InetSocketAddress.class, InetSocketAddressCodec.instance);
put(URI.class, URICodec.instance);
put(URL.class, URLCodec.instance);
put(Pattern.class, PatternCodec.instance);
put(Charset.class, CharsetCodec.instance);
}
……
}
三、反序列化
反序列化流程和序列化流程差不多,在這我就不過多介紹,感興趣的同學可以繼續查看源碼分析,培養閱讀源碼的興趣。