美文网首页程序员
fastjson序列化原理简单分析

fastjson序列化原理简单分析

作者: 极微 | 来源:发表于2020-07-03 17:25 被阅读0次

一、序列化概述

  • 序列化与反序列化概念
    序列化:将内存中的java对象转化为可供存储或可供传输的字节序列。
    反序列化:将字节序列转化为java对象。
  • 实现方式
    JDK原生的序列化与反序列化--需要实现Serializable接口。
    fastjson序列化与反序列化

二、fastjson序列化解析

以序列化Map对象为例
JSON.toJSONString(map)
发现最终调用的是JSON里面重载的toJSONString方法

public static String toJSONString(Object object, SerializeConfig config, SerializeFilter[] filters, String dateFormat, int defaultFeatures, SerializerFeature... features) {
        SerializeWriter out = new SerializeWriter((Writer)null, defaultFeatures, features);

        String var15;
        try {
            JSONSerializer serializer = new JSONSerializer(out, config);
            if (dateFormat != null && dateFormat.length() != 0) {
                serializer.setDateFormat(dateFormat);
                serializer.config(SerializerFeature.WriteDateUseDateFormat, true);
            }

            if (filters != null) {
                SerializeFilter[] var8 = filters;
                int var9 = filters.length;

                for(int var10 = 0; var10 < var9; ++var10) {
                    SerializeFilter filter = var8[var10];
                    serializer.addFilter(filter);
                }
            }

            serializer.write(object);
            var15 = out.toString();
        } finally {
            out.close();
        }

        return var15;
    }

跟踪serializer.write(object)方法,发现进入了MapSerializer的write方法。截取部分如下。

if (entryKey instanceof String) {
    strEntryKey = (String)entryKey;
    if (!first) {
        out.write(44);
    }

    if (out.isEnabled(SerializerFeature.PrettyFormat)) {
        serializer.println();
    }

    out.writeFieldName(strEntryKey, true);
} else {
    if (!first) {
        out.write(44);
    }

    if ((out.isEnabled(NON_STRINGKEY_AS_STRING) || SerializerFeature.isEnabled(features, SerializerFeature.WriteNonStringKeyAsString)) && !(entryKey instanceof Enum)) {
        strEntryKey = JSON.toJSONString(entryKey);
        serializer.write(strEntryKey);
    } else {
        serializer.write(entryKey);
    }

    out.write(58);
}

first = false;
if (value == null) {
    out.writeNull();
} else {
    Class<?> clazz = value.getClass();
    if (clazz != preClazz) {
        preClazz = clazz;
        preWriter = serializer.getObjectWriter(clazz);
    }

    if (SerializerFeature.isEnabled(features, SerializerFeature.WriteClassName) && preWriter instanceof JavaBeanSerializer) {
        Type valueType = null;
        if (fieldType instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType)fieldType;
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            if (actualTypeArguments.length == 2) {
                valueType = actualTypeArguments[1];
            }
        }

        JavaBeanSerializer javaBeanSerializer = (JavaBeanSerializer)preWriter;
        javaBeanSerializer.writeNoneASM(serializer, value, entryKey, valueType, features);
    } else {
        preWriter.write(serializer, value, entryKey, (Type)null, features);
    }
}

这个方法比较冗长,其大致意思是循环遍历Map的Entry,然后分别写入Entry的key和value。值得注意的是serializer.getObjectWriter(clazz)方法,即写入时会先获取value的class类型对应的writer进行写入。
跟踪serializer.getObjectWriter(clazz)方法,当clazz为自定义类型,发现调用了SerializeConfig.createJavaBeanSerializer(Class<?> clazz)方法。

public final ObjectSerializer createJavaBeanSerializer(Class<?> clazz) {
        String className = clazz.getName();
        long hashCode64 = TypeUtils.fnv1a_64(className);
        if (Arrays.binarySearch(this.denyClasses, hashCode64) >= 0) {
            throw new JSONException("not support class : " + className);
        } else {
            SerializeBeanInfo beanInfo = TypeUtils.buildBeanInfo(clazz, (Map)null, this.propertyNamingStrategy, this.fieldBased);
            return (ObjectSerializer)
              (beanInfo.fields.length == 0 && 
              Iterable.class.isAssignableFrom(clazz) ? MiscCodec.instance : 
              this.createJavaBeanSerializer(beanInfo));
        }
    }

其中TypeUtils.buildBeanInfo方法获取clazz的所有属性并创建一个beanInfo对象,并调用createJavaBeanSerializer(beanInfo)方法构造一个ObjectSerializer对象返回。
继续跟踪createJavaBeanSerializer(beanInfo),发现其最终返回了new JavaBeanSerializer(beanInfo),其主要属性如下

    protected final FieldSerializer[] getters;
    protected final FieldSerializer[] sortedGetters;
    protected SerializeBeanInfo beanInfo;

我们再跳回到MapSerializer的write方法,那么自定义类型时调用preWriter 写入的时候就是调用的JavaBeanSerializer的write方法。跟踪这个方法。

SerializeWriter out = serializer.out;
.
.
.
for(int i = 0; i < getters.length; ++i) {
      Field field = fieldSerializer.fieldInfo.field;
      FieldInfo fieldInfo = fieldSerializer.fieldInfo;
      out.write(fieldInfo.name_chars, 0, fieldInfo.name_chars.length);
}

其中会遍历其getters(若有排序则遍历sortedGetters),获取对象的每个属性,并调用out对象序列化输出属性名称和属性值。
到现在为止,我们大体清楚了fastjson序列化了哪些内容,下面再看下是怎么实现的。其关键是SerializeWriter对象。继续跟踪out.write(fieldInfo.name_chars, 0, fieldInfo.name_chars.length)方法。

public void write(char[] c, int off, int len) {
        if (off >= 0 && off <= c.length && len >= 0 && off + len <= c.length && off + len >= 0) {
            if (len != 0) {
                int newcount = this.count + len;
                if (newcount > this.buf.length) {//新的char[]实际长度>buf容量
                    if (this.writer == null) {
                        this.expandCapacity(newcount);//未指定writer则扩容
                    } else {
                        do {
                            int rest = this.buf.length - this.count;
                            System.arraycopy(c, off, this.buf, this.count, rest);
                            this.count = this.buf.length;
                            this.flush();//指定了writer则通过writer写出
                            len -= rest;
                            off += rest;
                        } while(len > this.buf.length);//剩余部分通过arraycopy拷贝到buf中

                        newcount = len;
                    }
                }

                System.arraycopy(c, off, this.buf, this.count, len);
                this.count = newcount;
            }
        } else {
            throw new IndexOutOfBoundsException();
        }
    }

public String toString() {
        return new String(this.buf, 0, this.count);
}

可以看出序列化的时候所有内容都保存在SerializeWriter的buf数组对象中,count就是buf的实际长度,JSON.toJSONString实际调用的是SerializeWriter的toString方法,展示的是bug这个字节数组。需要注意的是如果指定了writer对象,buf超长的情况下,toString展示的只是一部分序列化内容。

三、UML类图

相关文章

网友评论

    本文标题:fastjson序列化原理简单分析

    本文链接:https://www.haomeiwen.com/subject/bstrfktx.html