java序列化json原理_fastjson序列化原理详解

本文详细介绍了Fastjson的序列化过程,包括序列化API的使用、序列化配置、序列化过滤器和序列化器特性。重点讲解了序列化过程的入口方法`serializer.write(object)`,以及`SerializeConfig`在选择合适的`ObjectSerializer`中的作用。Fastjson预定义了多种类型的序列化器,可以处理基本类型、高精度数、日期时间等,并能识别Map、List、Collection等接口的实现类。对于不可识别的类型,Fastjson采用JavaBeanSerializer或ASM生成的子类进行序列化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

所有序列化的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,

// 内部保存着类型与对应的对象序列化器之间的映射关系

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,它的内部保存着所有被序列化对象的类型,与序列化此对象要使用的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接口类图如下:(点击可查看放大后的清晰图片)

6f56e693de8c66094d288c3d08664c86.png

整个体系共计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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值