nnonkey k1n9的博客

当你为错过太阳而哭泣时,你也要再错过群星了——泰戈尔​

fastjson底层分析

fastjson底层分析

测试代码

package demo2;
联想截图_20240329002549.png
public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}
package demo2;

import com.alibaba.fastjson.JSON;
public class FastjsonTest {
    public static void main(String[] args) {
        Person person = new Person("LJL", 18);
        String jsonString = JSON.toJSONString(person);//当然还有很多方法,这个不重要
        System.out.println(jsonString);
    }
}

过程分析

我们在String jsonString = JSON.toJSONString(person);这里下断点

跟进来到一堆重载的方法,根据你传入参数的类型来选择方法

我们传入的是这样的

public static String toJSONString(Object object) {
        return toJSONString(object, emptyFilters);
    }

来到我们的这个方法

public static String toJSONString(Object object, SerializerFeature... features) {
        return toJSONString(object, DEFAULT_GENERATE_FEATURE, features);
    }

SerializerFeature... features数组的意思,跟进看看这个方法

public enum SerializerFeature {
    QuoteFieldNames,
    UseSingleQuotes,
    WriteMapNullValue,
    WriteEnumUsingToString,
    WriteEnumUsingName,
    UseISO8601DateFormat,
    WriteNullListAsEmpty,
    WriteNullStringAsEmpty,
    WriteNullNumberAsZero,
    WriteNullBooleanAsFalse,
    SkipTransientField,
    SortField
    .....//很多不举了
    }

是一个定义json解析的配置吧

上面的分别代表不同的意思,你翻译一下差不能明白

比如第一个

QuoteFieldNames:
是否对字段名进行引号引用。默认情况下,字段名在 JSON 中是未引用的,但有些情况下(例如包含空格或特殊字符的字段名)可能需要对其进行引号引用。

然后我们传入的是emptyFilters,看看怎么个事

static final SerializeFilter[] emptyFilters = new SerializeFilter[0];
public interface SerializeFilter {
}

就是空的啥也不是

然后又会去到下一个方法

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;
    }

下面会涉及到非常多fastjson的类,这里说一下

SerializeConfig

看名字看的出来是配置,就是定义序列化的一些配置,比如
联想截图_20240329002549.png

SerializeFilterable

看名字就知道,是个过滤器

进去这个类可以发现

public abstract class SerializeFilterable {
    protected List<BeforeFilter> beforeFilters = null;
    protected List<AfterFilter> afterFilters = null;
    protected List<PropertyFilter> propertyFilters = null;
    protected List<ValueFilter> valueFilters = null;
    protected List<NameFilter> nameFilters = null;
    protected List<PropertyPreFilter> propertyPreFilters = null;
    protected List<LabelFilter> labelFilters = null;
    .......很多
    然后就是获得的方法比如
    public List<BeforeFilter> getBeforeFilters() {
        if (this.beforeFilters == null) {
            this.beforeFilters = new ArrayList();
            this.writeDirect = false;
        }
        就是你自己可以定义
    

SerializerFeature

这个类是一个枚举类型,它定义了一系列的特性,这些特性可以被用来定制 Fastjson 的序列化行为。

public enum SerializerFeature {
    QuoteFieldNames,
    /**
     * 
     */
    UseSingleQuotes,
    /**
     * 
     */
    WriteMapNullValue,
    /**
     * 用枚举toString()值输出
     */
    WriteEnumUsingToString,
    /**
     * 用枚举name()输出
     */
    WriteEnumUsingName,
    /**
     * 
     */
    UseISO8601DateFormat,
    /**
     * @since 1.1
     */
    WriteNullListAsEmpty,
    .....很多

比如

serializeConfig.putFeature(SerializerFeature.WriteMapNullValue); // 输出值为null的字段
serializeConfig.putFeature(SerializerFeature.WriteNullListAsEmpty); // 输出列表为null时写为[]

SerializeWriter

  1. 序列化对象SerializeWriter 可以将 Java 对象序列化为 JSON 格式的字符串。它支持多种数据类型的序列化,包括基本数据类型、字符串、数组、列表、地图等。
  2. 控制输出格式SerializeWriter 允许你控制输出的 JSON 字符串的格式,例如是否缩进、是否换行等。
  3. 自定义序列化规则:通过 SerializeWriter,你可以注册自定义的序列化器,以改变默认的序列化行为。这允许你为特定的类或全局配置序列化策略。

还有很多用途

JSONSerializer

JSONSerializer 是一个用于将 Java 对象序列化为 JSON 字符串的类。

回到正题

继续看我们的构造器

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

        try {
            JSONSerializer serializer = new JSONSerializer(out, config);//获取序列化对象的实例
            
            if (dateFormat != null && dateFormat.length() != 0) {
                serializer.setDateFormat(dateFormat);//设置我们的数据形式,因为dataFormat为空,默认
                serializer.config(SerializerFeature.WriteDateUseDateFormat, true);//设置我们数据的特点,就是前面讲的各种feature
            }

            if (filters != null) {
                for (SerializeFilter filter : filters) {
                    serializer.addFilter(filter);
                }
            }//如果我们filter不是空,循环获取我们的filter,增加进我们的序列化里面

            serializer.write(object);写入我们的序列化对象,就是person

            return out.toString();
        } finally {
            out.close();
        }
    }

最后会调用serializer.write(object);这个

我们跟进

public final void write(Object object) {
        if (object == null) {
            out.writeNull();
            return;
        }

        Class<?> clazz = object.getClass();//获取到person的class
        ObjectSerializer writer = getObjectWriter(clazz);//获取对象的writer

        try {
            writer.write(this, object, null, null, 0);
        } catch (IOException e) {
            throw new JSONException(e.getMessage(), e);
        }
    }

跟进getObjectWriter

  public ObjectSerializer getObjectWriter(Class<?> clazz) {
        return config.getObjectWriter(clazz);
    }

调用我们config的这个方法,跟进

联想截图_20240329114122.png

传入我们的clazz和create赋值为ture

然后就到下面的一个方法对我们进行一系列的判断

前面的判断都是没通过,最后到

if (create) {
                    put(clazz, createJavaBeanSerializer(clazz));
                }

到createJavaBeanSerializer这个方法
我们可以把JavaBeanSerializer理解为一个序列化的方式,这个方式运用于有setter,getter方法的对象

当然还有许多其他的序列化方式

 private final ObjectSerializer createJavaBeanSerializer(Class<?> clazz) {
        SerializeBeanInfo beanInfo = TypeUtils.buildBeanInfo(clazz, null, propertyNamingStrategy);
        if (beanInfo.fields.length == 0 && Iterable.class.isAssignableFrom(clazz)) {
            return MiscCodec.instance;
        }

        return createJavaBeanSerializer(beanInfo);
    }

进入buildBeanInfo方法看看怎么个事

    public static SerializeBeanInfo buildBeanInfo(Class<?> beanType //
                                                  , Map<String, String> aliasMap //
                                                  , PropertyNamingStrategy propertyNamingStrategy) {
        
        JSONType jsonType = beanType.getAnnotation(JSONType.class);//值为null,因为person根本没有注解

        Map<String, Field> fieldCacheMap = new HashMap<String, Field>();//创建一个map
        ParserConfig.parserAllFieldToCache(beanType, fieldCacheMap);//把beanType的field(name,age)都装进fieldCacheMap

        List<FieldInfo> fieldInfoList = computeGetters(beanType, jsonType, aliasMap, fieldCacheMap, false, propertyNamingStrategy);/使用computeGetters方法创建一个列表,这个方法会获取一堆东西,然后对获取到的进行判断,再获取一堆东西,见p1
       
        FieldInfo[] fields = new FieldInfo[fieldInfoList.size()];
        fieldInfoList.toArray(fields);
        
        String[] orders = null;//定义为null,下面会用到

        final int features;
        String typeName = null;
        if (jsonType != null) {
            orders = jsonType.orders();
            typeName = jsonType.typeName();
            if (typeName.length() == 0) {
                typeName = null;
            }
            features = SerializerFeature.of(jsonType.serialzeFeatures());
        } else {
            features = 0;
        }
        
        FieldInfo[] sortedFields;
        List<FieldInfo> sortedFieldList;
        if (orders != null && orders.length != 0) {
            sortedFieldList = TypeUtils.computeGetters(beanType, jsonType, aliasMap,fieldCacheMap, true, propertyNamingStrategy);
        } else {
            sortedFieldList = new ArrayList<FieldInfo>(fieldInfoList);
            Collections.sort(sortedFieldList);
        }//又创建了一个list,不过是sortlist,会进行排序,排序规则具体在sort方法里面
        sortedFields = new FieldInfo[sortedFieldList.size()];
        //然后就是创建一个sortedFields
        sortedFieldList.toArray(sortedFields);
        
        if (Arrays.equals(sortedFields, fields)) {
            sortedFields = fields;
        }//进行判断他们是否一样,是不一样的,因为他们的顺序不一样,具体见p2
        
        return new SerializeBeanInfo(beanType, jsonType, typeName, features, fields, sortedFields);//然后就是返回一个SerializeBeanInfo,包含着一些东西见p3
    }

p1

联想截图_20240329120821.png

p2

联想截图_20240329121352.png

p3

联想截图_20240329121713.png

回到我们的createJavaBeanSerializer走到下个

return createJavaBeanSerializer(beanInfo);

传入我们的获取的beaninfo

public ObjectSerializer createJavaBeanSerializer(SerializeBeanInfo beanInfo) {
        JSONType jsonType = beanInfo.jsonType;//还是为null,if不进入
        
        if (jsonType != null) {
            Class<?> serializerClass = jsonType.serializer();
            if (serializerClass != Void.class) {
                try {
                    Object seralizer = serializerClass.newInstance();
                    if (seralizer instanceof ObjectSerializer) {
                        return (ObjectSerializer) seralizer;
                    }
                } catch (Throwable e) {
                    // skip
                }
            }
            
            if (jsonType.asm() == false) {
                asm = false;
            }
        }
        
        Class<?> clazz = beanInfo.beanType;//获取person的class
        if (!Modifier.isPublic(beanInfo.beanType.getModifiers())) {//检查beanInfo.beanType修饰是不是public  getModifiers获取修饰符 因为是public跳过
            return new JavaBeanSerializer(beanInfo);
        }

        boolean asm = this.asm; //asm为ture

        if (asm && asmFactory.classLoader.isExternalClass(clazz)//使用asmFactory创建的类加载器来判断clazz是否是由其他应用程序或JVM加载器加载的外部类。见p1 所以跳过if
                || clazz == Serializable.class || clazz == Object.class) {
            asm = false;
        }

        if (asm && !ASMUtils.checkName(clazz.getSimpleName())) {
            asm = false;
        }
        //遍历字段,看看有没有JSONField注解,有的话进一步检查,看看能不能被asm处理
        if (asm) {
            for(FieldInfo field : beanInfo.fields){
                JSONField annotation = field.getAnnotation();
                
                if (annotation == null) {
                    continue;
                }
                if ((!ASMUtils.checkName(annotation.name())) //
                        || annotation.format().length() != 0
                        || annotation.jsonDirect()
                        || annotation.serializeUsing() != Void.class
                        ) {
                    asm = false;
                    break;
                }
            }
        }
        
        if (asm) {//如果所有字段都适合使用ASM,代码将尝试创建一个ObjectSerializer
            try {
                ObjectSerializer asmSerializer = createASMSerializer(beanInfo);
                if (asmSerializer != null) {
                    return asmSerializer;
                }
            } catch (ClassFormatError e) {
                // skip
            } catch (ClassCastException e) {
                // skip
            } catch (Throwable e) {
                throw new JSONException("create asm serializer error, class "
                        + clazz, e);
            }
        }

        return new JavaBeanSerializer(beanInfo);
    }

    public boolean isAsmEnable() {
        return asm;
    }

    public void setAsmEnable(boolean asmEnable) {
        if (ASMUtils.IS_ANDROID) {
            return;
        }
        this.asm = asmEnable;
    }

    public static SerializeConfig getGlobalInstance() {
        return globalInstance;
    }

    public SerializeConfig() {
        this(1024);
    }

总的来说这段代码的目的是为了在可能的情况下使用ASM来优化序列化过程,但如果有任何条件导致ASM不适合使用,它将退回到传统的JavaBean序列化方法。

p1

isExternalClass判断的依据是

public boolean isExternalClass(Class<?> clazz) {
        ClassLoader classLoader = clazz.getClassLoader();

        if (classLoader == null) {
            return false;
        }//我们的person是已经被加载过,所以可以获得它的类加载器为AppClassLoader

image-20240329131635926

回到put(clazz, createJavaBeanSerializer(clazz));
现在我们已经把

createJavaBeanSerializer(clazz)作为value加入到clazz这个key

然后来到

writer = serializers.get(clazz);

用于从serializers映射中获取与clazz对应的序列化器实例。如果serializers是一个Map,那么这个方法会返回与clazz键关联的值。
然后return writer;

回到梦开始的地方,我们终于有writer了,可以调用这个方法了

JSON类的

serializer.write(object);//序列化对象

联想截图_20240329131614.png

最后输出,这里就完成了

总结

1.因为我们要JSON.toJSONString(person);解析我们的person,所以会到toJSONString这个方法,并且完成一些基础的东西,比如config,filter这些,最后获取到我们配置好的 serializer

2.重点就在序列化的地方serializer.write(object);

这里调用write方法,在这个方法里会getObjectWriter,获取对象的write

3.会进入到config的这个重写方法,只要我们的writer为null,就会通过一些判读为我们获取合适的writer

4.最后我们的create为ture,走到createJavaBeanSerializer方法,通过JavaBeanSerializer这种序列化形式

5.在createJavaBeanSerializer方法中会干这戏事情

  1. 确定 JSON 类型:通过 jsonType 属性,可以知道是否有特定的序列化类被定义来处理这个 Bean。如果有,并且这个类不是 Void.class,那么尝试创建这个类的实例。
  2. 设置 ASM 模式asm 变量表示是否使用 ASM 字节码操作框架来优化序列化过程。如果 jsonType.asm() 返回 false,则不使用 ASM。
  3. 检查类是否为公开的:如果 Bean 类不是公开的(即 Modifier.isPublic(beanInfo.beanType.getModifiers()) 返回 false),则直接创建一个 JavaBeanSerializer 实例。
  4. 检查类是否为内部类:如果类是通过 ASM 加载的,或者它是 Serializable.classObject.class,则不使用 ASM。
  5. 检查字段注解:如果使用了 ASM 模式,并且字段上没有特定的注解(如 JSONField),则继续检查其他字段。如果任何一个字段有注解(例如有特定的字段名或格式化要求),则关闭 ASM 模式。
  6. 尝试创建 ASM 序列化器:如果所有条件都满足,尝试使用 ASM 模式来创建一个序列化器。如果成功,则返回这个 ASM 序列化器。
  7. 返回默认的 JavaBeanSerializer:如果没有合适的序列化器被创建(无论是通过特定的序列化类,还是通过 ASM 模式),则返回一个默认的 JavaBeanSerializer 实例。

最终返回一个序列化器

6.然后这个put方法就为这个clazz得到新value,最后获取到我们的writer = serializers.get(clazz);返回

7.获得好了writer以后回到JSONservilize类为

ObjectSerializer writer = getObjectWriter(clazz);为这个赋值
8.然后立马调用它去序列化我们的对象回到JSON类

serializer.write(object);,说明序列化操作终于结束

9.return out.toString();然后利用out的tosting输出

out就是SerializeWriter,这个类可以定于输出的样式

10.回到我们的测试类,成功输出序列化后的数据{"age":18,"name":"LJL"}结束

本原创文章未经允许不得转载 | 当前页面:nnonkey k1n9的博客 » fastjson底层分析

评论 10

  1. alert(1)

    Aiwin 2024-04-02    回复
  2. Aiwin 2024-04-02    回复
  3. <A HREF=\"http://ha.ckers.org@google\">XSS</A>

    Aiwin 2024-04-02    回复
  4. <a href="http://www.baidu.com">XSS</a>

    Aiwin 2024-04-02    回复
  5. <script>alert(1)</script>

    Aiwin 2024-04-02    回复
  6. aaaa

    Aiwin 2024-04-02    回复
  7. alert(1)

    ljl 2024-07-14    回复
  8. alert(1)

    ljl 2024-07-14    回复
  9. alert(1)

    ljl 2024-07-14    回复
  10. XSS

    ljl 2024-07-14    回复