结论

  1. parse(jsonStr) :自动调用构造方法+Json字符串指定属性的setter()+特殊的getter()
  2. parseObject(jsonStr) :自动调用构造方法+Json字符串指定属性的setter()+所有getter() 。包括不存在属性和私有属性的getter()
  3. parseObject(jsonStr,Object.class) :自动调用构造方法+Json字符串指定属性的setter()+特殊的getter()

关键分析

一、序列化数据中类的获取方式

fastjson在调用toJSONString方法时如果指定SerializerFeature.WriteClassName参数时会在序列化时额外写入 Java 对象所属的类名(@type 属性),如果不指定则序列化数据中不会包含类名。

如果指定参数,那么在调用parseObject方法进行反序列化过程中就会识别@type头来获取对象的所属类。

先分析一下类的获取方式

通过断点的跟踪可以判断@type头的识别在com.alibaba.fastjson.parser.JSONLexerBase#scanSymbol(com.alibaba.fastjson.parser.SymbolTable, char)方法中进行

跟进

代码会逐字符的读取直到遇到结束的引号,将读取的结果赋值给key

整个调用栈如下:

二、parseObject(String text)反序列化过程中获取getter/setter方法

编写示例代码开始调试

package org.atoposx;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.atoposx.model.Evil;

public class FastJsonTest {
    public static void main(String[] args) {
        Evil evil = new Evil("evil test");
        System.out.println("-------------------------------------");
/*        String jsonString1 = JSON.toJSONString(evil, SerializerFeature.WriteClassName);
        System.out.println(jsonString1);
        String jsonString2 = JSON.toJSONString(evil);
        System.out.println(jsonString2);*/
        String jsonString = "{\"@type\":\"org.atoposx.model.Evil\",\"cmd\":\"evil test\"}";
        System.out.println("-------------------------------------");
//        JSON.parseObject(jsonString, Evil.class);
        System.out.println("-------------------------------------");
        ParserConfig.getGlobalInstance().setAsmEnable(false);
        JSON.parseObject(jsonString);
        System.out.println("-------------------------------------");
//        JSON.parse(jsonString);
    }
}

步入parseObject(String text)方法

步入com.alibaba.fastjson.JSON#parse(java.lang.String)方法

步入com.alibaba.fastjson.parser.DefaultJSONParser#parse()方法

步入com.alibaba.fastjson.parser.DefaultJSONParser#parse(java.lang.Object)方法

此处对lexer token做了一个判断,作用是通过不同的token类型调用不同的解析逻辑。

token类型有以下几种

  - SET/TREE_SET: 特殊集合类型
  - LBRACKET: JSON数组开始标记 [
  - LBRACE: JSON对象开始标记 {
  - LITERAL_INT: 整数字面量
  - LITERAL_FLOAT: 浮点数字面量
  - LITERAL_STRING: 字符串字面量
  - NULL/UNDEFINED: 空值
  - TRUE/FALSE: 布尔值
  - NEW: 构造函数调用(如Date对象)
  - EOF: 文件结束
  - ERROR: 错误标记

由于传入的是json格式的字符串,所以这里识别出的token就是LBRACE

步入1327行com.alibaba.fastjson.parser.DefaultJSONParser#parseObject(java.util.Map, java.lang.Object)方法

往下走就来到了一中的识别@type头,获取类的过程,此处不再赘述

步入第367行com.alibaba.fastjson.parser.ParserConfig#getDeserializer(java.lang.reflect.Type)方法

在该方法中获取不到默认的反序列化器就会步入312行com.alibaba.fastjson.parser.ParserConfig#getDeserializer(java.lang.Class<?>, java.lang.reflect.Type)方法

往下走到第362行会经过一个黑名单判断

该过程是防止AutoType反序列化的关键步骤,不允许黑名单中的类进行反序列化,如果匹配到直接抛出异常

往下走

371行和386行的会对jdk8和java.awt.开头的一些类做特殊处理,此处不进行分析

步入第461行com.alibaba.fastjson.parser.ParserConfig#createJavaBeanDeserializer

该方法用于创建一个javabean类型的反序列化器

方法开始会对是否开启asm加速做一个判断

启用asm会提高性能,直接生成字节码,避免反射调用,所以不会走进invoke方法,不方便理解整个调用过程,所以在测试代码中禁用了asm加速。

步入586行com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer方法

步入关键方法39行com.alibaba.fastjson.util.JavaBeanInfo#build

前面部分在获取一些类的基本信息,比如fields、方法等。一直跟进到328行

遍历method获取setter方法需要满足5个条件:

  1. 方法名长度>4
  2. 非静态方法
  3. 返回类型是void或者当前类
  4. 传入参数个数必须是1
  5. 方法开头是set

后续代码对方法名进行处理,提取其中的属性值

最后将setter方法的相关信息储存到fieldList数组中

获取完setter之后,从490行开始获取getter方法

getter方法需要满足以下几个条件:

  1. 方法名称长度≥4
  2. 非静态方法
  3. 方法名称开头是get
  4. 传入参数个数是0
  5. 方法继承了Collection||Map||AtomicBoolean||AtomicInteger||AtomicLong

三、parseObject(String text)反序列化过程中自动调用getter/setter方法

setter的调用

在二中获取完setter方法后,一路return,退出com.alibaba.fastjson.parser.ParserConfig#getDeserializer(java.lang.reflect.Type)方法。

步入368行com.alibaba.fastjson.parser.deserializer.ObjectDeserializer#deserialze方法

步入com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer#deserialze(com.alibaba.fastjson.parser.DefaultJSONParser, java.lang.reflect.Type, java.lang.Object, java.lang.Object, int)方法

这里可以成功步入deserialze方法是因为一开始设置了关闭asm加速,不然程序直接从内存中进行调用,无法通过断点调试看到invoke过程。

一路步过,一直到593行

步入com.alibaba.fastjson.parser.deserializer.FieldDeserializer#setValue(java.lang.Object, java.lang.Object)

一直到96行可以看到调用了invoke方法

至此调用了setter方法

getter方法调用

一路步过,回到com.alibaba.fastjson.JSON#parseObject(java.lang.String)方法

步入com.alibaba.fastjson.JSON#toJSON(java.lang.Object)方法

872行获取类名

896行为获取的类创建序列化器,比如为Map类创建MapSerializer序列化器,为List类创建ListSerializer序列化器等,如果都没有匹配就会为JavaBean类型创建 JavaBeanSerializer序列化器。此处的evil类是标准javabean就会进入897行的if语句

之后步入关键方法902行com.alibaba.fastjson.serializer.JavaBeanSerializer#getFieldValuesMap,该方法会获取javabean对象中的字段->字段值,会调用对象的所有getter方法

sortedGetters会将所有getter方法缓存成FieldSerializer数组,循环获取字段和字段值。

439行通过com.alibaba.fastjson.serializer.FieldSerializer#getPropertyValue方法,反射调用对象的所有getter方法

整个过程调用栈如下