项目和第三方对接,有接口一直调不通。直到我拿到合作方的入参后,问题来了,有了接下来的一系列故事。
拿到原生的第三方参数(JSON格式的),为了节省时间,迫不及待地直接在本地单元测试一波。熟悉的操作,这里为了方便观察,我模拟一次请求从controller进入的请求:
import com.alibaba.fastjson.JSON;
import lombok.Data;
public class ProFastjson {
@Data
static class Teacher {
private String teacherName;
}
private static TeacherController teacherController = new TeacherController();
public static void main(String[] args) {
String str = "{\"teacher_name\":\"zxerjones\"}";
Teacher teacher = JSON.parseObject(str, Teacher.class);
teacherController.search(teacher);
}
}
看重点:我的JSONString参数名有下划线,Teacher的是没有teacher_name这个属性的,反序列化之后的值应该是空的,可偏偏方法走通了。不甘心的我决定debug一波,如下图:
反序列化成功了,是不是一脸懵逼。没错FASTJson就是不和你讲道理。
行吧,那一定是是FASTJson内部的反序列化机制造成这样的结果,debug进源码看看:
注意看上图378行,JSON的反序列化就是在这个方法中实现的,继续跟进:
上图对一些规则进行校验之后,开始进入主题。正式调用反序列化工具JavaBeanDeserializer.deserialze对字符进行反序列化。这个方法主要做的事情就是对JSON字符串内部的键值对和我们需要的反序列化结果类进行绑定,赋值(这个方法代码比较多,只贴重点):下图是赋值的过程,这才是导致问题的关键:
上图方法内部做的事情就是生成field反序列化工具对field反序列化,然后赋值。这个field反序列化工具从何而来断点打到1089行,可以看到,这个方法返回了我们需要的工具,点进去:
- ‘-’和‘_’不参与hash运算;
- 忽略大小写。
根据最后得出的hash规则,那么可以在json字符串中随意的添加"_","-",并且大小写忽略都可以反序列化成功。证实下猜想:如下代码
public static void main(String[] args) {
String str = "{\"TEACHER___---NAME\":\"zxerjones\"}";
Teacher teacher = JSON.parseObject(str, Teacher.class);
System.out.println(teacher);
}
运行结果:
ProFastjson.Teacher(teacherName=zxerjones)
Process finished with exit code 0
猜想成立,问题解决。血一样的教训:能用postman就不要用单元测试。~~(╯﹏╰)~~