這個更新了兩次,跳過分析可以直接看分割線后面的內容,即可解決。
今天遇到了一個奇怪的問題,使用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這個字段。