fastjson序列化原理詳解

全部序列化的API都在JSON類中,方法名稱爲toJSONString,或者咱們也能夠設計本身的序列化方法,代碼以下:java

public class MyJSON {

	
	public static String toJSONString(Object object, SerializeConfig config, SerializeFilter[] filters,
			SerializerFeature[] features) {
		SerializeWriter out = new SerializeWriter();

		try {
			// SerializeConfig能夠理解爲一個Map<Type,ObjectSerializer>,
			// 內部保存着類型與對應的對象序列化器之間的映射關係
			if (config == null)
				config = SerializeConfig.getGlobalInstance();
			// 核心序列化器,主要負責調用SerializeConfig根據value選擇合適的對象序列化器
			// 內部還保存着輸出流對象,以及各類過濾器
			JSONSerializer serializer = new JSONSerializer(out, config);
			// 全部特性最終會合成爲一個int值,保存在輸出流對象中
			if (features != null)
				for (SerializerFeature feature : features) {
					serializer.config(feature, true);
				}
			// 如上面所說,過濾器保存在覈心序列化器中
			if (filters != null && filters.length > 0)
				setFilter(serializer, filters);
			// 序列化過程的入口方法
			serializer.write(object);

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

	private static void setFilter(JSONSerializer serializer, SerializeFilter... filters) {
		for (SerializeFilter filter : filters) {
			setFilter(serializer, filter);
		}
	}

	private static void setFilter(JSONSerializer serializer, SerializeFilter filter) {
		if (filter == null) {
			return;
		}

		if (filter instanceof PropertyPreFilter) {
			serializer.getPropertyPreFilters().add((PropertyPreFilter) filter);
		}

		if (filter instanceof NameFilter) {
			serializer.getNameFilters().add((NameFilter) filter);
		}

		if (filter instanceof ValueFilter) {
			serializer.getValueFilters().add((ValueFilter) filter);
		}

		if (filter instanceof PropertyFilter) {
			serializer.getPropertyFilters().add((PropertyFilter) filter);
		}

		if (filter instanceof BeforeFilter) {
			serializer.getBeforeFilters().add((BeforeFilter) filter);
		}

		if (filter instanceof AfterFilter) {
			serializer.getAfterFilters().add((AfterFilter) filter);
		}

		if (filter instanceof LabelFilter) {
			serializer.getLabelFilters().add((LabelFilter) filter);
		}
	}
}

調用方法時須要傳入一個要序列化的目標對象object,以及三個可選參數,分別爲SerializeConfig、SerializeFilter[]、SerializerFeature[]。這三個參數之因此爲可選,是由於它們均有默認配置。spring

  1. SerializeConfig:序列化配置,咱們能夠把它理解爲一個Map<Class,ObjectSerializer>,它的內部保存着全部被序列化對象的類型,與序列化此對象要使用的ObjectSerializer序列化器之間的映射關係。另外,若是遇到不存在的javaBean類型,它的內部還能夠自動建立JavaBeanSerializer(包括直接建立JavaBeanSerializer對象,或者經過asm框架建立ASMJavaBeanSerializer的子類對象)。sql

  2. SerializeFilter:序列化過濾器???json

  3. SerializerFeature:序列化器特性,主要用於控制序列化過程當中的一些行爲特性數組

序列化過程的入口其實就是serializer.write(object);方法的調用,具體執行過程以下:oracle

public final void write(Object object) {
		// 若是value爲null則直接輸出"null"並返回
		if (object == null) {
			out.writeNull();
			return;
		}
		// 獲取value對象的類型
		Class<?> clazz = object.getClass();
		// 根據Class類型,從SerializeConfig中選擇合適的ObjectSerializer
		ObjectSerializer writer = getObjectWriter(clazz);

		try {
			// 調用ObjectSerializer序列化這個value
			// 由於輸入的初始value對象沒有與之對應的字段名稱,
			// 所以第三(字段名稱)和第四(字段類型)兩個參數爲null
			writer.write(this, object, null, null, 0);
		} catch (IOException e) {
			throw new JSONException(e.getMessage(), e);
		}
	}

這就是爲何我說JSONSerializer只負責調用SerializeConfig選擇合適的ObjectSerializer進行序列化的緣由。框架


所以,咱們須要關注的重點有三個:ui

  1. fastjson內部有多少種對象序列化器(即ObjectSerializer有多少個實現類)?this

  2. 每種對象序列化器是如何工做的?atom

  3. SerializeConfig中有多少種類型與對象序列化器之間的映射關係

ObjectSerializer接口類圖以下:(點擊可查看放大後的清晰圖片)

整個體系共計61個實現類,以及一個子接口(AutowiredObjectSerializer)

具體每種對象序列化器如何工做,我會單開專題講解

在SerializeConfig的構造方法中,會添加許多默認支持的映射關係,每一個新建立的SerializeConfig對象,都會支持這些類型的序列化。

                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(File.class, FileCodec.instance);
		put(URI.class, URICodec.instance);
		put(URL.class, URLCodec.instance);
		put(Appendable.class, AppendableSerializer.instance);
		put(StringBuffer.class, AppendableSerializer.instance);
		put(StringBuilder.class, AppendableSerializer.instance);
		put(Pattern.class, PatternCodec.instance);
		put(Charset.class, CharsetCodec.instance);

		// atomic
		put(AtomicBoolean.class, AtomicBooleanSerializer.instance);
		put(AtomicInteger.class, AtomicIntegerSerializer.instance);
		put(AtomicLong.class, AtomicLongSerializer.instance);
		put(AtomicReference.class, ReferenceCodec.instance);
		put(AtomicIntegerArray.class, AtomicIntegerArrayCodec.instance);
		put(AtomicLongArray.class, AtomicLongArrayCodec.instance);
		
		put(WeakReference.class, ReferenceCodec.instance);
		put(SoftReference.class, ReferenceCodec.instance);

		// awt
		if (!awtError) {
    		try {
    			put(Class.forName("java.awt.Color"), ColorCodec.instance);
    			put(Class.forName("java.awt.Font"), FontCodec.instance);
    			put(Class.forName("java.awt.Point"), PointCodec.instance);
    			put(Class.forName("java.awt.Rectangle"),
    					RectangleCodec.instance);
    		} catch (Throwable e) {
    		    awtError = true;
    			// skip
    		}
		}
		
		// jdk8
		if (!jdk8Error) {
    		try {
    		    put(Class.forName("java.time.LocalDateTime"), Jdk8DateCodec.instance);
    		    put(Class.forName("java.time.LocalDate"), Jdk8DateCodec.instance);
    		    put(Class.forName("java.time.LocalTime"), Jdk8DateCodec.instance);
    		    put(Class.forName("java.time.ZonedDateTime"), Jdk8DateCodec.instance);
    		    put(Class.forName("java.time.OffsetDateTime"), Jdk8DateCodec.instance);
    		    put(Class.forName("java.time.OffsetTime"), Jdk8DateCodec.instance);
    		    put(Class.forName("java.time.ZoneOffset"), Jdk8DateCodec.instance);
    		    put(Class.forName("java.time.ZoneRegion"), Jdk8DateCodec.instance);
    		    put(Class.forName("java.time.Period"), Jdk8DateCodec.instance);
    		    put(Class.forName("java.time.Duration"), Jdk8DateCodec.instance);
    		    put(Class.forName("java.time.Instant"), Jdk8DateCodec.instance);
    		} catch (Throwable e) {
    		    // skip
    		    jdk8Error = true;
    		}
		}
		
		if (!oracleJdbcError) {
		    try {
                put(Class.forName("oracle.sql.DATE"), DateSerializer.instance);
                put(Class.forName("oracle.sql.TIMESTAMP"), DateSerializer.instance);
            } catch (Throwable e) {
                // skip
                oracleJdbcError = true;
            }
		}

所以,fastjson預約義的ObjectSerializer可識別的類型包括:

  1. 基本類型包裝類:Boolean、Character、Byte、Short、Integer、Long、Float、Double

  2. 高精度數:BigDecimal、BigInteger

  3. String

  4. 基本類型的數組:boolean[]、char[]、byte[]、short[]、int[]、long[]、float[]、double[]

  5. Object[]、Class、SimpleDateFormat、Locale、Currency、TimeZone、UUID、InetAddress、Inet4Address、Inet6Address、InetSocketAddress、File、URI、URL、Appendable、StringBuffer、StringBuilder、Pattern、Charset

  6. 原子性對象:AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference、AtomicIntegerArray、AtomicLongArray

  7. 引用對象:WeakReference、SoftReference

  8. awt相關類型:java.awt.Color、java.awt.Font、java.awt.Point、java.awt.Rectangle

  9. jdk8特有類型(java.time包中):LocalDateTime、LocalDate、LocalTime、ZonedDateTime、OffsetDateTime、OffsetTime、ZoneOffset、ZoneRegion、Period、Duration、Instant

  10. oracle特有類型(oracle.sql包中):DATE、TIMESTAMP

另外,fastjson還能夠識別一些類型,不光能夠識別這些類型,還能夠識別這些類型的全部子類。因爲不肯定這些類具體有多少子類,不可能提早把這些子類的Class對象都添加到map中。所以採起的是,只要某一類型是這些可識別類型或其子類,則即時添加到SerializeConfig中。舉個例子:fastjson能夠識別全部Map接口的實現類,但不可能提早知道咱們自定義的Map接口實現類(如:MyMap.class),因此當遇到這個自定義實現類的時候,才把映射關係添加到map中。

這些可識別的類型包括:

  1. Map接口及其實現類

  2. List接口及其實現類

  3. Collection接口及其實現類

  4. Date及其子類

  5. JSONAware及其實現類

  6. JSONSerializable接口及其實現類

  7. JSONStreamAware接口及其實現類

  8. 枚舉類型及其子類

  9. 數組類型

  10. Throwable及其子類

  11. TimeZone及其子類

  12. Appendable及其子類

  13. Charset及其子類

  14. Enumeration及其子類

  15. Calendar及其子類

  16. Clob及其子類

除了以上提到的這些全部類型外,其餘類型所有爲不可識別類型。對於不可識別的類型,所有使用JavaBeanSerializer或者ASMJavaBeanSerializer的子類(asm動態生成)進行序列化。


SerializeConfig選擇序列化器的邏輯以下:

public ObjectSerializer getObjectWriter(Class<?> clazz) {
		// 從已存在的映射關係中,查找序列化器
		ObjectSerializer writer = get(clazz);
		// 若是沒有找到
		if (writer == null) {
			try {
				// 獲取當前線程使用的類加載器
				final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
				// 使用類加載器嘗試加載"META-INF/services/com.alibaba.fastjson.serializer.AutowiredObjectSerializer"
				// 這個文件中保存的全部類(一行一個類的全限定名),並調用無參構造建立對象
				for (Object o : ServiceLoader.load(AutowiredObjectSerializer.class, classLoader)) {
					// 若是該類沒有實現AutowiredObjectSerializer則忽略
					if (!(o instanceof AutowiredObjectSerializer)) {
						continue;
					}

					AutowiredObjectSerializer autowired = (AutowiredObjectSerializer) o;
					// 把這個序列化器能夠處理的類型集合添加到map中
					for (Type forType : autowired.getAutowiredFor()) {
						put(forType, autowired);
					}
				}
			} catch (ClassCastException ex) {
				// skip
			}
			// 再次嘗試獲取對象序列化器
			writer = get(clazz);
		}
		// 若是仍是沒有找到
		if (writer == null) {
			// 獲取加載JSON類的類加載器
			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()) {
							put(forType, autowired);
						}
					}
				} catch (ClassCastException ex) {
					// skip
				}
				// 再次嘗試獲取
				writer = get(clazz);
			}
		}
		// 若是仍找不到,則進行下面的邏輯處理
		if (writer == null) {
			if (Map.class.isAssignableFrom(clazz)) {
				put(clazz, MapSerializer.instance);
			} else if (List.class.isAssignableFrom(clazz)) {
				put(clazz, ListSerializer.instance);
			} else if (Collection.class.isAssignableFrom(clazz)) {
				put(clazz, CollectionSerializer.instance);
			} else if (Date.class.isAssignableFrom(clazz)) {
				put(clazz, DateSerializer.instance);
			} else if (JSONAware.class.isAssignableFrom(clazz)) {
				put(clazz, JSONAwareSerializer.instance);
			} else if (JSONSerializable.class.isAssignableFrom(clazz)) {
				put(clazz, JSONSerializableSerializer.instance);
			} else if (JSONStreamAware.class.isAssignableFrom(clazz)) {
				put(clazz, JSONStreamAwareSerializer.instance);
			} else if (clazz.isEnum() || (clazz.getSuperclass() != null && clazz.getSuperclass().isEnum())) {
				put(clazz, EnumSerializer.instance);
			} else if (clazz.isArray()) {
				Class<?> componentType = clazz.getComponentType();
				ObjectSerializer compObjectSerializer = getObjectWriter(componentType);
				put(clazz, new ArraySerializer(componentType, compObjectSerializer));
			} else if (Throwable.class.isAssignableFrom(clazz)) {
				put(clazz, new ExceptionSerializer(clazz));
			} else if (TimeZone.class.isAssignableFrom(clazz)) {
				put(clazz, TimeZoneCodec.instance);
			} else if (Appendable.class.isAssignableFrom(clazz)) {
				put(clazz, AppendableSerializer.instance);
			} else if (Charset.class.isAssignableFrom(clazz)) {
				put(clazz, CharsetCodec.instance);
			} else if (Enumeration.class.isAssignableFrom(clazz)) {
				put(clazz, EnumerationSeriliazer.instance);
			} else if (Calendar.class.isAssignableFrom(clazz)) {
				put(clazz, CalendarCodec.instance);
			} else if (Clob.class.isAssignableFrom(clazz)) {
				put(clazz, ClobSeriliazer.instance);
			} else {
				boolean isCglibProxy = false;
				boolean isJavassistProxy = false;
				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;
					}
				}

				if (isCglibProxy || isJavassistProxy) {
					Class<?> superClazz = clazz.getSuperclass();

					ObjectSerializer superWriter = getObjectWriter(superClazz);
					put(clazz, superWriter);
					return superWriter;
				}

				if (Proxy.isProxyClass(clazz)) {
					put(clazz, createJavaBeanSerializer(clazz));
				} else {
					put(clazz, createJavaBeanSerializer(clazz));
				}
			}

			writer = get(clazz);
		}
		return writer;
	}
相關文章
相關標籤/搜索