Json序列化利器FastJSON


首先介绍一篇文章, 【问底】静行:FastJSON实现详解 http://www.csdn.net/article/2014-09-25/2821866

这篇文章讲到FastJSON通过createJavaBeanSerializer()创建的序列化类。通过该方法会获取两种序列化类,一种是直接的JavaBeanSerializer(根据类的get方法、public filed等JavaBean特征序列化),另一种是createASMSerializer(通过ASM框架生成的序列化字节码),优先使用第二种。

---------------------------------------------

看了FastJSON实现后,发现这种序列化方式和ProtoBuf很类似。在序列化类的基础上进行封装,就没有那么多的反射了(反射挺消耗时间的)

我们这里来分析下: 首先将类ASMSerializerFactory中方法createJavaBeanSerializer的IOUtils.write注释代码取消。修改下输出路径。

//
 org.apache.commons.io.IOUtils.write(code, new java.io.FileOutputStream(
 "/Users/jiaojianfeng/Documents/empleyment/tmp/fastjson/"
 + className + ".class"));

我们将生成的Serialize0.class反编译后得到:

import com.alibaba.fastjson.serializer.FilterUtils;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.JavaBeanSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.alibaba.fastjson.serializer.SerialContext;
import com.alibaba.fastjson.serializer.SerializeWriter;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.util.ASMUtils;
import com.jjf.Person;
import java.io.IOException;
import java.lang.reflect.Type;

public class Serialize0 implements ObjectSerializer {
    private JavaBeanSerializer nature;
    public Type name_asm_fieldPrefix;
    public Type name_asm_fieldType = ASMUtils.getMethodType(Person.class,
            "getName");
    public Type age_asm_fieldPrefix;
    public Type age_asm_fieldType = ASMUtils.getMethodType(Person.class,
            "getAge");

    public void write(JSONSerializer paramJSONSerializer, Object paramObject1,
            Object paramObject2, Type paramType) throws IOException {
        SerializeWriter localSerializeWriter = paramJSONSerializer.getWriter();
        if (localSerializeWriter.isEnabled(SerializerFeature.SortField)) {
            write1(paramJSONSerializer, paramObject1, paramObject2, paramType);
            return;
        }
        Person localPerson = (Person) paramObject1;
        if (localSerializeWriter.isEnabled(SerializerFeature.PrettyFormat)) {
            if (this.nature == null)
                this.nature = new JavaBeanSerializer(Person.class);
            this.nature.write(paramJSONSerializer, paramObject1, paramObject2,
                    paramType);
            return;
        }
        if (paramJSONSerializer.containsReference(paramObject1)) {
            if (this.nature == null)
                this.nature = new JavaBeanSerializer(Person.class);
            this.nature.writeReference(paramJSONSerializer, paramObject1);
            return;
        }
        if (paramJSONSerializer.isWriteAsArray(paramObject1, paramType)) {
            writeAsArray(paramJSONSerializer, paramObject1, paramObject2,
                    paramType);
            return;
        }
        SerialContext localSerialContext = paramJSONSerializer.getContext();
        paramJSONSerializer.setContext(localSerialContext, paramObject1,
                paramObject2);
        localSerializeWriter.write("{\"@type\":\"com.jjf.Person\"");
        char c = (paramJSONSerializer.isWriteClassName(paramType, paramObject1))
                && (paramType != paramObject1.getClass()) ? ',' : '{';
        c = FilterUtils.writeBefore(paramJSONSerializer, paramObject1, c);
        String str1 = "name";
        Object localObject1;
        Object localObject2;
        if (FilterUtils.applyName(paramJSONSerializer, paramObject1, str1)) {
            String str2 = localPerson.getName();
            if (FilterUtils
                    .apply(paramJSONSerializer, paramObject1, str1, str2)) {
                str1 = FilterUtils.processKey(paramJSONSerializer,
                        paramObject1, str1, str2);
                localObject1 = str2;
                localObject2 = FilterUtils.processValue(paramJSONSerializer,
                        paramObject1, str1, localObject1);
                if (localObject1 != localObject2) {
                    if (localObject2 == null) {
                        if (localSerializeWriter
                                .isEnabled(SerializerFeature.WriteMapNullValue)) {
                            localSerializeWriter.writeFieldNullString(c, str1);
                            c = ',';
                        }
                    } else {
                        localSerializeWriter.write(c);
                        localSerializeWriter.writeFieldName(str1);
                        paramJSONSerializer.writeWithFieldName(localObject2,
                                str1, this.name_asm_fieldType);
                        c = ',';
                    }
                } else if (str2 == null) {
                    if (localSerializeWriter
                            .isEnabled(SerializerFeature.WriteMapNullValue)) {
                        localSerializeWriter.writeFieldNullString(c, str1);
                        c = ',';
                    }
                } else {
                    localSerializeWriter.writeFieldValue(c, str1, str2);
                    c = ',';
                }
            }
        }
        str1 = "age";
        if (FilterUtils.applyName(paramJSONSerializer, paramObject1, str1)) {
            int i = localPerson.getAge();
            if (FilterUtils.apply(paramJSONSerializer, paramObject1, str1, i)) {
                str1 = FilterUtils.processKey(paramJSONSerializer,
                        paramObject1, str1, i);
                localObject1 = Integer.valueOf(i);
                localObject2 = FilterUtils.processValue(paramJSONSerializer,
                        paramObject1, str1, localObject1);
                if (localObject1 != localObject2) {
                    if (localObject2 == null) {
                        if (localSerializeWriter
                                .isEnabled(SerializerFeature.WriteMapNullValue)) {
                            localSerializeWriter.writeFieldNull(c, str1);
                            c = ',';
                        }
                    } else {
                        localSerializeWriter.write(c);
                        localSerializeWriter.writeFieldName(str1);
                        paramJSONSerializer.writeWithFieldName(localObject2,
                                str1);
                        c = ',';
                    }
                } else {
                    localSerializeWriter.writeFieldValue(c, str1, i);
                    c = ',';
                }
            }
        }
        c = FilterUtils.writeAfter(paramJSONSerializer, paramObject1, c);
        if (c == '{')
            localSerializeWriter.write('{');
        localSerializeWriter.write('}');
        paramJSONSerializer.setContext(localSerialContext);
    }

    public void write1(JSONSerializer paramJSONSerializer, Object paramObject1,
            Object paramObject2, Type paramType) throws IOException {
        SerializeWriter localSerializeWriter = paramJSONSerializer.getWriter();
        Person localPerson = (Person) paramObject1;
        if (localSerializeWriter.isEnabled(SerializerFeature.PrettyFormat)) {
            if (this.nature == null)
                this.nature = new JavaBeanSerializer(Person.class);
            this.nature.write(paramJSONSerializer, paramObject1, paramObject2,
                    paramType);
            return;
        }
        if (paramJSONSerializer.containsReference(paramObject1)) {
            if (this.nature == null)
                this.nature = new JavaBeanSerializer(Person.class);
            this.nature.writeReference(paramJSONSerializer, paramObject1);
            return;
        }
        if (paramJSONSerializer.isWriteAsArray(paramObject1, paramType)) {
            writeAsArray(paramJSONSerializer, paramObject1, paramObject2,
                    paramType);
            return;
        }
        SerialContext localSerialContext = paramJSONSerializer.getContext();
        paramJSONSerializer.setContext(localSerialContext, paramObject1,
                paramObject2);
        localSerializeWriter.write("{\"@type\":\"com.jjf.Person\"");
        char c = (paramJSONSerializer.isWriteClassName(paramType, paramObject1))
                && (paramType != paramObject1.getClass()) ? ',' : '{';
        c = FilterUtils.writeBefore(paramJSONSerializer, paramObject1, c);
        String str1 = "age";
        Object localObject1;
        Object localObject2;
        if (FilterUtils.applyName(paramJSONSerializer, paramObject1, str1)) {
            int i = localPerson.getAge();
            if (FilterUtils.apply(paramJSONSerializer, paramObject1, str1, i)) {
                str1 = FilterUtils.processKey(paramJSONSerializer,
                        paramObject1, str1, i);
                localObject1 = Integer.valueOf(i);
                localObject2 = FilterUtils.processValue(paramJSONSerializer,
                        paramObject1, str1, localObject1);
                if (localObject1 != localObject2) {
                    if (localObject2 == null) {
                        if (localSerializeWriter
                                .isEnabled(SerializerFeature.WriteMapNullValue)) {
                            localSerializeWriter.writeFieldNull(c, str1);
                            c = ',';
                        }
                    } else {
                        localSerializeWriter.write(c);
                        localSerializeWriter.writeFieldName(str1);
                        paramJSONSerializer.writeWithFieldName(localObject2,
                                str1);
                        c = ',';
                    }
                } else {
                    localSerializeWriter.writeFieldValue(c, str1, i);
                    c = ',';
                }
            }
        }
        str1 = "name";
        if (FilterUtils.applyName(paramJSONSerializer, paramObject1, str1)) {
            String str2 = localPerson.getName();
            if (FilterUtils
                    .apply(paramJSONSerializer, paramObject1, str1, str2)) {
                str1 = FilterUtils.processKey(paramJSONSerializer,
                        paramObject1, str1, str2);
                localObject1 = str2;
                localObject2 = FilterUtils.processValue(paramJSONSerializer,
                        paramObject1, str1, localObject1);
                if (localObject1 != localObject2) {
                    if (localObject2 == null) {
                        if (localSerializeWriter
                                .isEnabled(SerializerFeature.WriteMapNullValue)) {
                            localSerializeWriter.writeFieldNullString(c, str1);
                            c = ',';
                        }
                    } else {
                        localSerializeWriter.write(c);
                        localSerializeWriter.writeFieldName(str1);
                        paramJSONSerializer.writeWithFieldName(localObject2,
                                str1, this.name_asm_fieldType);
                        c = ',';
                    }
                } else if (str2 == null) {
                    if (localSerializeWriter
                            .isEnabled(SerializerFeature.WriteMapNullValue)) {
                        localSerializeWriter.writeFieldNullString(c, str1);
                        c = ',';
                    }
                } else {
                    localSerializeWriter.writeFieldValue(c, str1, str2);
                    c = ',';
                }
            }
        }
        c = FilterUtils.writeAfter(paramJSONSerializer, paramObject1, c);
        if (c == '{')
            localSerializeWriter.write('{');
        localSerializeWriter.write('}');
        paramJSONSerializer.setContext(localSerialContext);
    }

    public void writeAsArray(JSONSerializer paramJSONSerializer,
            Object paramObject1, Object paramObject2, Type paramType)
            throws IOException {
        SerializeWriter localSerializeWriter = paramJSONSerializer.getWriter();
        Person localPerson = (Person) paramObject1;
        localSerializeWriter.write('[');
        String str = "age";
        localSerializeWriter.writeIntAndChar(localPerson.getAge(), ',');
        str = "name";
        localSerializeWriter.writeString(localPerson.getName(), ']');
    }
}

序列化时调用的就是write方法。读者可以将源码修改下,让其调用类Serialize0的write方法,方便调试,查看处理过程。

当然,FastJSON中还有很多优化方案,像工具类SerializeWriter、IdentityHashMap、sort field、sort field fast match 等等。可自行通过源码学习。


上篇: 序列化利器kryo 下篇: Java动态代理原理-字节码