这个更新了两次,跳过分析可以直接看分割线后面的内容,即可解决。
今天遇到了一个奇怪的问题,使用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这个字段。