摘要:某年某月的某一天,本汪在某個奇葩的公司,接手了某個奇葩的項目,遇到了一些奇葩的事情,就掉進關于做轉換時,那些關于首字符大小寫的坑。坑首字符小寫,第二個字符大寫的鍵名這個坑與相關,嚴格來說,應該是挖的坑。
某年某月的某一天,本汪在某個奇葩的公司,接手了某個奇葩的項目,遇到了一些奇葩的事情,就掉進關于fastjson做bean to json轉換時,那些關于首字符大小寫的坑。
這個奇葩項目里面,api接口定義的是天馬行空、云山霧繞,api里面的字段定義更是五花八門、千奇百怪,完全沒有規則可言,都可以開個不符合規范的案例博物館了。下面3個坑里面舉的例子,那些奇葩的名稱定義,都是在項目里面真實存在的,如有雷同,純屬不幸。
在api的處理過程里面,bean轉換成json時,我們總是希望字段名是什么樣的,轉換成json就應該是什么樣的,然而現實總是殘酷的。
坑0x01 全大寫的鍵名這種情況在api定義里面很常見,如下:
private String TEST = “1”; public String getTEST() { return this.TEST}
在fastjson轉換后,變成:json{ “tEST”: ”1”},與預期不符,首字母變成小寫了。
原因:
fastjson在將bean轉換為json時,先取出對應的methodName: getTEST,從methodName的第4個字符開始,取出propertyName:TEST,它默認認為這個propertyName的首字母是在定義getter的時候被寫成大寫的,現在要轉成小寫:
propertyName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
結果,正確的TEST就被轉成錯誤的tEST了。
解決:
解決這個問題比較簡單,在轉換前,多加一行代碼:
TypeUtils.compatibleWithJavaBean =true;
此時,fastjson會先判斷propertyName長度大于1、且頭兩個字符都是大寫時,不做轉換:
if(name.length() > 1 && Character.isUpperCase(name.charAt(1)) && Character.isUpperCase(name.charAt(0))){ return name; }
也就是說,連續大寫開頭的propertyName,在轉換時,會保持原樣。
坑0x02 第一個字符大寫,第二個字符不是大寫的鍵名按坑0x01里面講的設置TypeUtils.compatibleWithJavaBean=true后,如果有如下的鍵名,依然會出問題:
private String T_EST = “1”; private String Test = “2”; public String getT_EST() { return this.T_EST} public String getTest() { return this.Test}
在fastjson轉換后,變成:{ “t_EST”: ”1”, “test”:”2”},又是一個坑。
原因:
從坑0x01的最后一段代碼可以看出,要想fastjson不改首字符,除了需要設置compatibleWithJavaBean外,propertyName的第二個字符也必須是大寫。在坑0x02這里,兩個propertyName都無法通過判斷,首字母就要被轉換成小寫了。
解決
要解決這個問題,在轉換前,必須再加一行代碼:
TypeUtils.compatibleWithFieldName = true;
Fastjson里面對應的處理代碼如下:
if(compatibleWithFieldName){ if(!fieldCacheMap.containsKey(propertyName)){ String tempPropertyName = methodName.substring(fromIdx); return fieldCacheMap.containsKey(tempPropertyName) ? tempPropertyName : propertyName; } }
fastjson在按坑0x01所述的過程處理完propertyName后,propertyName的首字符被轉換為小寫,然后會在bean的的field列表里面找一遍轉換后的名稱。如果找不到,就從methodName里面重新取get后面的字符串,然后再到field列表里面找一遍,如果找到,就用原propertyName,如果找不到就用首字符被轉換的名稱。
坑0x03 首字符小寫,第二個字符大寫的鍵名這個坑與lombok相關,嚴格來說,應該是lombok挖的坑。
如上所述,就算你按坑0x01、0x02設置了,如果在工程里面用lombok時,有如下的鍵名定義,依然要被坑:
@Getter private String iPhone = “1”;
在fastjson轉換后,變成:{ “IPhone”: ”1” },首字符變大寫了,WTF!
原因:
Lombok在自動生成getter的時候,會把propertyName的第一的字母改成大寫,等同如下代碼:
public String getIPhone(){return this.iPhone;}
問題就出在這個轉換上,get后面緊跟的字符變成大寫了。在eclipse、idea里面,如果自動生成代碼,get后的字符是小寫。
如前面坑0x01最后一段代碼,fastjson在處理getter時,會判斷前兩個字符是不是大寫,如果是的話,就保持原樣,取到的propertyName就成了:IPhone。但是在field列表里面,對應的propertyName是iPhone,就算開啟了compatibleWithFieldName,fastjson用從getter中解析出來的IPhone,在field列表里面也找不到對應值,也只能保持IPhone這個名稱了。
另外,就算在屬性前用了@JSONField(name = “iPhone”)注解,因為fastjson用從getter解析出來的propertyName找不到對應的field,也無法讀出該field對應的注解,這個注解也是無效的。
解決
碰到這種propertyName,就不要用lombok生成的getter/setter了,自己寫,保持首字符小寫,如:getiPhone/setiPhone,只要在代碼里面有這兩個方法,lombok就不會自動生成,lombok是按忽略大小寫后的propertyName判斷的。
把propertyName第二個字符改成小寫,或者重新取個名字,并用@JSONField注明正確的名稱,如:
@Getter @ JSONField(name = “iPhone”) private String iphone = “1”;
關于lombok的這個坑,可以參考:http://xxxx.ooo/2017/using-lo...,lombok的作者也是死鴨子嘴硬,被提了n多的issue,就是不改。
以上,就是本汪在項目里面填坑的過程,不要問我為什么api里面的字段名稱會定義成這副模樣,本汪也不知道,汪!汪!!汪!!!
關于fastjson的代碼,都在TypeUtils.computeGetters里面。
@JSONField是個好東西,不嫌麻煩的話,就都加上吧。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/71572.html
摘要:文件夾中的文件首字母大寫。因為在中我沒有找到日期和字符串轉換和格式化的靈活方法,所以在中處理格式化的問題。獲取參數由于框架自身設計的問題,推薦盡量用方式請求后臺服務,參數格式為格式。 1.controllers文件夾中的controller文件首字母大寫。不大寫也可以,但是環境兼容性不好,舉個例子,我開發環境在mac電腦上,文件名首字母小寫,服務可以正常訪問;但是在阿里云服務器(deb...
摘要:不同編碼器編碼的相同的字符,最終的字節大小可能會不同。對于和,是由于對應編碼不能處理字符串字節導致的。在另外兩個規范化形式和的首字母縮略詞中,字母表示兼容性。最后是雙模,同一函數能接受字符串和字節進行操作。 對于字符串,我們接觸得挺多的。而編碼問題,也不時令人頭疼的。 由于一開始接觸的就是 Python3,所以一些在 Python2 上的編碼上的坑我沒遇到,甚至在 Python3 上都...
摘要:前言的介紹協議使用方便,越來越流行的處理器有很多這里我介紹一下是阿里的開源框架被不少企業使用是一個極其優秀的框架地址的特點數度快無論序列化和反序列化都是當之無愧的功能強大支持普通類包括任意或零依賴沒有依賴其它任何類庫的簡單說明對于格式字符串 1.前言 1.1.FastJson的介紹: JSON協議使用方便,越來越流行,JSON的處理器有很多,這里我介紹一下FastJson,FastJs...
摘要:學習第一課變量注釋輸出上圖是一段超級簡單的輸出的代碼,是不是超級簡單呢今天文章講的就是這幾行代碼的知識。變量可以通過變量名訪問。用來定義聲明一個變量。有返回值,總是返回。輸出格式化的字符串,有返回值,返回值是輸出的字符串的長度。 來一波 Hello World,各位看官先感受下。PHP學習第一課:變量、注釋、輸出上圖是一段超級簡單的輸出 Hello World 的代碼,是不是超級簡單呢...
摘要:為數組示例說明在中將字符串替換為即可。返回其中如果的數組值比的數組值長,將中多出來的數組元素在中匹配的字符串替換為空串,返回。 字符串大小寫轉換 strtoupper(string $str) //把字符串全部轉換成大寫字母 strtolower(string $str) //把字符串全部轉換成小寫字母 ucfirst(string $str) //把字符串的首字母轉換成大寫 ucw...
閱讀 5257·2021-09-22 15:50
閱讀 1863·2021-09-02 15:15
閱讀 1164·2019-08-29 12:49
閱讀 2543·2019-08-26 13:31
閱讀 3458·2019-08-26 12:09
閱讀 1210·2019-08-23 18:17
閱讀 2736·2019-08-23 17:56
閱讀 2929·2019-08-23 16:02