FastJson中一些较少提到的特性

都是23年11月左右自己看源码+调试测出来的特性,结果后来发现早两年就有人研究过Constructor的调用逻辑了((((((

添加白名单绕过特性应该也挺早就被前人发现过,最终在22年下旬造成了最近的一次绕过

调用Constructor机制

低版本

目标类必须有**默认方法,FastJson反序列化时也只会调用default-constructor**

没有就报错,此时都没有缓存机制

高版本

开了AutoType后,利用缓存机制多打几次就可以打破默认构造方法的必要性限制

这样就能调用无参以外的构造方法

然而有好几个限制点:

  • 如果目标类有默认构造方法,就不会调用有参构造方法

  • 如果调用有参构造方法,就不会在反序列化阶段调用任何setter与getter

  • 与Jackson不同,在FastJson中通过**传String类型的参数调用对应setter, 不能自动做类型转换而调用setter的参数类** 的**String类型的构造方法**(这本来也不该能调用,我实在不知道为什么Jackson支持)

    那么调用目标的什么构造方法呢?参照第一点,FastJson仍然会优先调用默认构造方法创建对象,并调用setter、getter,都不行就反射修改public属性来赋值

    如果类压根没有这个属性(父类私有) 就去往上找父类,找到第一个有这个属性的父类就开始调用setter/getter/… 最终会赋给子类就离谱()

顺序

  • 按照getConstructors()获取到的顺序,取第一位调用,这个过程甚至可能随机: https://zhuanlan.zhihu.com/p/535423876

  • 顺序不受Json数据影响,假如有AB两个构造方法,其中A的参数是A1、A2,B的参数是B1、B2;传A1A2,如果B的顺序更先,它宁愿给B1B2初始化默认值,也不会调用A方法

总结

相比于Jackson、Snakeyaml

FastJson

  • 很难调用到想要的有参Constructor

  • 若有一个不会被拦截的类,其中具有setXxxxx….(Classpath….)方法,且拥有Default-Constructor(如果用缓存绕过默认限制,会导致走不到借助settter实现的绕过逻辑),则Classpath…..可以蹭车通过checkAutoType ——从而调用到对应的setter,不能调getter,但可以调指定有参构造方法,但也别忘了————

    如果调用的是有参构造方法,就不会在反序列化阶段调用任何setter与getter

第二点在[新思路](1.2.68 & 1.2.80新思路.md)里有更详细的说明,具体可用于添加白名单缓存