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
看名字看的出来是配置,就是定义序列化的一些配置,比如
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
- 序列化对象:
SerializeWriter
可以将 Java 对象序列化为 JSON 格式的字符串。它支持多种数据类型的序列化,包括基本数据类型、字符串、数组、列表、地图等。 - 控制输出格式:
SerializeWriter
允许你控制输出的 JSON 字符串的格式,例如是否缩进、是否换行等。 - 自定义序列化规则:通过
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的这个方法,跟进
传入我们的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
p2
p3
回到我们的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
回到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);//序列化对象
最后输出,这里就完成了
总结
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方法中会干这戏事情
- 确定 JSON 类型:通过
jsonType
属性,可以知道是否有特定的序列化类被定义来处理这个 Bean。如果有,并且这个类不是Void.class
,那么尝试创建这个类的实例。 - 设置 ASM 模式:
asm
变量表示是否使用 ASM 字节码操作框架来优化序列化过程。如果jsonType.asm()
返回false
,则不使用 ASM。 - 检查类是否为公开的:如果 Bean 类不是公开的(即
Modifier.isPublic(beanInfo.beanType.getModifiers())
返回false
),则直接创建一个JavaBeanSerializer
实例。 - 检查类是否为内部类:如果类是通过 ASM 加载的,或者它是
Serializable.class
或Object.class
,则不使用 ASM。 - 检查字段注解:如果使用了 ASM 模式,并且字段上没有特定的注解(如
JSONField
),则继续检查其他字段。如果任何一个字段有注解(例如有特定的字段名或格式化要求),则关闭 ASM 模式。 - 尝试创建 ASM 序列化器:如果所有条件都满足,尝试使用 ASM 模式来创建一个序列化器。如果成功,则返回这个 ASM 序列化器。
- 返回默认的 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"}结束
alert(1)
<A HREF=\"http://ha.ckers.org@google\">XSS</A>
<a href="http://www.baidu.com">XSS</a>
<script>alert(1)</script>
aaaa
alert(1)
alert(1)
alert(1)
XSS