一、序列化概述
- 序列化与反序列化概念
序列化:将内存中的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展示的只是一部分序列化内容。
网友评论