項(xiàng)目和第三方對接牺蹄,有接口一直調(diào)不通。直到我拿到合作方的入?yún)⒑蟊〕幔瑔栴}來了沙兰,有了接下來的一系列故事氓奈。
拿到原生的第三方參數(shù)(JSON格式的),為了節(jié)省時間鼎天,迫不及待地直接在本地單元測試一波舀奶。熟悉的操作,這里為了方便觀察斋射,我模擬一次請求從controller進(jìn)入的請求:
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);
}
}
看重點(diǎn):我的JSONString參數(shù)名有下劃線育勺,Teacher的是沒有teacher_name這個屬性的,反序列化之后的值應(yīng)該是空的罗岖,可偏偏方法走通了涧至。不甘心的我決定debug一波,如下圖:
反序列化成功了桑包,是不是一臉懵逼南蓬。沒錯FASTJson就是不和你講道理。
行吧捡多,那一定是是FASTJson內(nèi)部的反序列化機(jī)制造成這樣的結(jié)果蓖康,debug進(jìn)源碼看看:
注意看上圖378行,JSON的反序列化就是在這個方法中實(shí)現(xiàn)的垒手,繼續(xù)跟進(jìn):
上圖對一些規(guī)則進(jìn)行校驗(yàn)之后,開始進(jìn)入主題倒信。正式調(diào)用反序列化工具JavaBeanDeserializer.deserialze對字符進(jìn)行反序列化科贬。這個方法主要做的事情就是對JSON字符串內(nèi)部的鍵值對和我們需要的反序列化結(jié)果類進(jìn)行綁定,賦值(這個方法代碼比較多鳖悠,只貼重點(diǎn)):下圖是賦值的過程榜掌,這才是導(dǎo)致問題的關(guān)鍵:
上圖方法內(nèi)部做的事情就是生成field反序列化工具對field反序列化卡辰,然后賦值胞皱。這個field反序列化工具從何而來斷點(diǎn)打到1089行,可以看到九妈,這個方法返回了我們需要的工具反砌,點(diǎn)進(jìn)去:
- ‘-’和‘_’不參與hash運(yùn)算锭吨;
- 忽略大小寫蠢莺。
根據(jù)最后得出的hash規(guī)則,那么可以在json字符串中隨意的添加"_","-",并且大小寫忽略都可以反序列化成功耐齐。證實(shí)下猜想:如下代碼
public static void main(String[] args) {
String str = "{\"TEACHER___---NAME\":\"zxerjones\"}";
Teacher teacher = JSON.parseObject(str, Teacher.class);
System.out.println(teacher);
}
運(yùn)行結(jié)果:
ProFastjson.Teacher(teacherName=zxerjones)
Process finished with exit code 0
猜想成立浪秘,問題解決。血一樣的教訓(xùn):能用postman就不要用單元測試埠况。~~(╯﹏╰)~~