1. 程式人生 > >FastJson用註解@JSONField將json轉為bean實體類,將bean實體類toString的時候欄位屬性名未變的錯誤分析

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這個欄位。