欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

fastjson序列化原理详解

发布时间:2025/4/5 编程问答 47 豆豆
生活随笔 收集整理的这篇文章主要介绍了 fastjson序列化原理详解 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

2019独角兽企业重金招聘Python工程师标准>>>

所有序列化的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中选择合适的ObjectSerializerObjectSerializer writer = getObjectWriter(clazz);try {// 调用ObjectSerializer序列化这个value// 因为输入的初始value对象没有与之对应的字段名称,// 因此第三(字段名称)和第四(字段类型)两个参数为nullwriter.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);// atomicput(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);// awtif (!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}}// jdk8if (!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) {// skipjdk8Error = true;}}if (!oracleJdbcError) {try {put(Class.forName("oracle.sql.DATE"), DateSerializer.instance);put(Class.forName("oracle.sql.TIMESTAMP"), DateSerializer.instance);} catch (Throwable e) {// skiporacleJdbcError = 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;}


    转载于:https://my.oschina.net/lixin91/blog/634969

    总结

    以上是生活随笔为你收集整理的fastjson序列化原理详解的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。