所有序列化的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[]。这三个参数之所以为可选,是因为它们均有默认配置。
SerializeConfig:序列化配置,我们可以把它理解为一个Map<Class,ObjectSerializer>,它的内部保存着所有被序列化对象的类型,与序列化此对象要使用的ObjectSerializer序列化器之间的映射关系。另外,如果遇到不存在的javaBean类型,它的内部还可以自动创建JavaBeanSerializer(包括直接创建JavaBeanSerializer对象,或者通过asm框架创建ASMJavaBeanSerializer的子类对象)。
SerializeFilter:序列化过滤器???
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进行序列化的原因。
因此,我们需要关注的重点有三个:
fastjson内部有多少种对象序列化器(即ObjectSerializer有多少个实现类)?
每种对象序列化器是如何工作的?
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可识别的类型包括:
基本类型包装类:Boolean、Character、Byte、Short、Integer、Long、Float、Double
高精度数:BigDecimal、BigInteger
String
基本类型的数组:boolean[]、char[]、byte[]、short[]、int[]、long[]、float[]、double[]
Object[]、Class、SimpleDateFormat、Locale、Currency、TimeZone、UUID、InetAddress、Inet4Address、Inet6Address、InetSocketAddress、File、URI、URL、Appendable、StringBuffer、StringBuilder、Pattern、Charset
原子性对象:AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference、AtomicIntegerArray、AtomicLongArray
引用对象:WeakReference、SoftReference
awt相关类型:java.awt.Color、java.awt.Font、java.awt.Point、java.awt.Rectangle
jdk8特有类型(java.time包中):LocalDateTime、LocalDate、LocalTime、ZonedDateTime、OffsetDateTime、OffsetTime、ZoneOffset、ZoneRegion、Period、Duration、Instant
oracle特有类型(oracle.sql包中):DATE、TIMESTAMP
另外,fastjson还可以识别一些类型,不光可以识别这些类型,还可以识别这些类型的所有子类。由于不确定这些类具体有多少子类,不可能提前把这些子类的Class对象都添加到map中。因此采取的是,只要某一类型是这些可识别类型或其子类,则即时添加到SerializeConfig中。举个例子:fastjson可以识别所有Map接口的实现类,但不可能提前知道我们自定义的Map接口实现类(如:MyMap.class),所以当遇到这个自定义实现类的时候,才把映射关系添加到map中。
这些可识别的类型包括:
Map接口及其实现类
List接口及其实现类
Collection接口及其实现类
Date及其子类
JSONAware及其实现类
JSONSerializable接口及其实现类
JSONStreamAware接口及其实现类
枚举类型及其子类
数组类型
Throwable及其子类
TimeZone及其子类
Appendable及其子类
Charset及其子类
Enumeration及其子类
Calendar及其子类
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;
}