fastjson序列化原理详解

原创
2016/03/11 10:58
阅读数 9.2K

所有序列化的API都在JSON类中,方法名称为toJSONString,或者我们也可以设计自己的序列化方法,代码如下:

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[]。这三个参数之所以为可选,是因为它们均有默认配置。

  1. SerializeConfig:序列化配置,我们可以把它理解为一个Map<Class,ObjectSerializer>,它的内部保存着所有被序列化对象的类型,与序列化此对象要使用的ObjectSerializer序列化器之间的映射关系。另外,如果遇到不存在的javaBean类型,它的内部还可以自动创建JavaBeanSerializer(包括直接创建JavaBeanSerializer对象,或者通过asm框架创建ASMJavaBeanSerializer的子类对象)。

  2. SerializeFilter:序列化过滤器???

  3. SerializerFeature:序列化器特性,主要用于控制序列化过程中的一些行为特性

序列化过程的入口其实就是serializer.write(object);方法的调用,具体执行过程如下:

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进行序列化的原因。


因此,我们需要关注的重点有三个:

  1. fastjson内部有多少种对象序列化器(即ObjectSerializer有多少个实现类)?

  2. 每种对象序列化器是如何工作的?

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


展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
1
分享
返回顶部
顶部