FastJson用註解@JSONField將json轉為bean實體類,將bean實體類toString的時候欄位屬性名未變的錯誤分析
這個更新了兩次,跳過分析可以直接看分割線後面的內容,即可解決。
今天遇到了一個奇怪的問題,使用FastJson的註解@JSONField的時候,出現了一個奇怪的問題。
我將json通過FastJson轉為bean的時候,由於json有些欄位不合規範,用了註解@JSONField,但是toString的時候,不是自定義的欄位,而是註解的name,比如@JSONField(name = "rtuUid"),toString,欄位名稱還是rtuUid,但是在其他位置,又可以getLampID()。這樣描述估計不好理解,直接上程式碼。
這是基礎資訊實體類。
package org.xlink.cecep.server; import java.util.Date; import org.springframework.data.annotation.Id; import com.alibaba.fastjson.JSON; import lombok.Data; /** * 公共欄位 * * @author lk.timeout */ @Data public class BaseEntity { @Id protected String _id; @Override public String toString() { return JSON.toJSONString(this); } /** * corpId : 企業ID */ protected String corpId; /** * projectId : 專案ID */ protected String projectId; /** * vendorType : 廠家型別 */ protected String vendorType; /** * devictType : 裝置型別 */ protected Integer deviceType; /** * 是否物聯裝置 */ protected String iotType; /** * deviceId : 裝置在其他平臺的唯一ID */ protected String deviceId; /** * date : 獲取資料時間 */ protected Date date; }
這是子類,繼承於上面的父類。
package org.xlink.cecep.server; import com.alibaba.fastjson.annotation.JSONField; import lombok.Getter; import lombok.Setter; /** * 路燈 * * @author lk.timeout */ @Getter @Setter //@ToString 這裡是問題所在,重寫toString的方法即可修復此問題。 public class Lamp extends BaseEntity { /** * lampID : 燈具序號 */ @JSONField(name = "rtuUid") private String lampID; /** * lampIndex : 燈頭號 */ @JSONField(name = "rtuID") private String lampIndex; private String name; private String ccuUid; private String ccuName; private String runMode; private String voltage; private String current; private String power; private String powerFactor; private String energy; private String comm; private String fault; private String status; private String dimming; private String leakageVoltage; private String workDuration; }
測試類
package org.xlink.cecep.server; import java.util.List; import com.alibaba.fastjson.JSONArray; public class TestEveryThing { public static void main(String[] args) { // TODO Auto-generated method stub String test = "[{\"alarmAndClose\":0,\"ccuIP\":\"28.684\",\"ccuName\":\"贛江中大道\",\"ccuUid\":\"00000000DD3A\",\"comm\":\"Y\"," + "\"config\":\"Y\",\"current\":\"0.83\",\"energy\":\"3891213056.000\",\"fault\":\"N\",\"gpsShield\":0,\"interruptMode\":1," + "\"isFillInLightRtuCtrl\":\"N\",\"lampAlarmThreshold\":75,\"lampShellIsAlarm\":\"N\",\"lampSwap\":\"N\",\"latitude\":28.693574," + "\"leakageActionSwitch\":0,\"leakageSwitch\":0,\"leakageVoltage\":null,\"lightThreshold\":15,\"longitude\":115.873829,\"name\":" + "\"09002116-1\",\"offlineTime\":null,\"power\":\"186.72\",\"powerFactor\":\"0.98\",\"protocolType\":\"\",\"rtuID\":153,\"rtuTime" + "\":null,\"rtuUid\":\"00000002F230\",\"rtuVersion\":null,\"rtuVolUp\":0.0,\"runMode\":\"\",\"shellTamperShield\":0,\"stat\":\"1\"," + "\"status\":1,\"tempTestShield\":0,\"tiltActionSwitch\":0,\"tiltSwitch\":0,\"volLeakage\":0.0,\"voltage\":\"231.19\",\"workDuration\":\"6922233\"}]"; List<Lamp> ts = JSONArray.parseArray(test, Lamp.class); System.out.println(ts.toString()); } }
執行結果:
這個時候你會發現,我明明定義了lampID這個欄位,為什麼輸出的還是rtuUid這些欄位。因為你沒有重寫toString的方法,FastJson不會幫你做轉換,他只是幫你把值對映在改欄位屬性上面。如果在子類Lamp重寫toString的方法,就好了。
[{
"ccuName": "贛江中大道",
"ccuUid": "00000000DD3A",
"comm": "Y",
"current": "0.83",
"energy": "3891213056.000",
"fault": "N",
"name": "09002116-1",
"power": "186.72",
"powerFactor": "0.98",
"rtuID": "153",
"rtuUid": "00000002F230",
"runMode": "",
"status": "1",
"voltage": "231.19",
"workDuration": "6922233"
}]
最後:說明一下為什麼會有子類父類,因為這個問題是這樣觸發,因為父類重寫了toString的方法,所以在列印的時候就能看到欄位,所以忽略這個問題。一般單獨的實體類要列印,肯定會重寫toString的方法。
個人覺的跟lombok應該是沒有關係的,但是因為用了,但是自己也沒有單獨驗證,所以放在這裡,如有有人跟我一樣的錯誤,可以自己測試下。
分割線 分割線 分割線 分割線
今天(2018.08.25)有時間,發現上面的重寫toString方法,只是在列印的時候能正確列印到屬性以及值,但是轉為json的時候,還是會出問題,還是不能正確列印自定義的屬性欄位。
經過今天的仔細研究fastjson的@JSONField,發現get和set方法都可以進行註解。用了LomBok之後,get和set方法均是rtuUid這個欄位,所以在轉為jsonString的時候,就不是我們自定義屬性的值。
@JSONField 註解定義了輸入的key以及輸出的key,如果不在get和set方法上面分開定義,就會出錯,所以應按照如下方式編寫程式碼,不能偷懶試用lombok。
如下圖:
set的時候定義一個name,那麼json轉bean的時候,就會用rtuUid值匹配到lampID。
同理get的時候,bean轉json的時候,就會獲取lampID這個欄位。