关于@JsonView的使用心得及一些隐蔽的注意事项
程序员文章站
2022-06-08 17:02:55
...
关于@JsonView的使用心得
一、一般情况下的使用
1、声明View接口
在你想要声明多个视图的类中定义相应视图的view接口,视图之间可以继承,子视图会包含父视图的内容
2、在属性的get方法上指定视图
如果你想要某一个属性在某一种视图中出现,那么只需在对应属性的get方法上使用@JsonView注解声明其所在视图即可。本文在Notification类中声明三个视图,如下:
public class Notification implements Serializable{
private static final long serialVersionUID = -2200572370385250074L;
public interface AlertView{}
public interface CNView extends AlertView{}
public interface MNView extends CNView{}
private BigInteger id;
private Integer type;
private String holder;
private String time;
private String reason;
private boolean isRead;
private String protrait;
private String detail;
private String address;
private String company;
private String roomId;
private String latitude;
private String longitude;
private String image;
private List<String> devices;
private String instruction;
private Integer capacity;
private List<String> roomImages;
private List<Attendees> attendees;
private Booking booking;
public Notification() {
}
@JsonView(MNView.class)
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
@JsonView(AlertView.class)
public BigInteger getId() {
return id;
}
public void setId(BigInteger id) {
this.id = id;
}
@JsonView(AlertView.class)
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
@JsonView(CNView.class)
public String getHolder() {
return holder;
}
public void setHolder(String holder) {
this.holder = holder;
}
@JsonView(CNView.class)
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
@JsonView(AlertView.class)
public boolean isRead() {
return isRead;
}
public void setRead(boolean read) {
isRead = read;
}
@JsonView(CNView.class)
public String getProtrait() {
return protrait;
}
public void setProtrait(String protrait) {
this.protrait = protrait;
}
@JsonView(CNView.class)
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
@JsonView(CNView.class)
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@JsonView(CNView.class)
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
@JsonView(CNView.class)
public String getRoomId() {
return roomId;
}
public void setRoomId(String roomId) {
this.roomId = roomId;
}
@JsonView(CNView.class)
public String getLatitude() {
return latitude;
}
public void setLatitude(String latitude) {
this.latitude = latitude;
}
@JsonView(CNView.class)
public String getLongitude() {
return longitude;
}
public void setLongitude(String longitude) {
this.longitude = longitude;
}
@JsonView(CNView.class)
public String getInstruction() {
return instruction;
}
public void setInstruction(String instruction) {
this.instruction = instruction;
}
@JsonView(CNView.class)
public Integer getCapacity() {
return capacity;
}
public void setCapacity(Integer capacity) {
this.capacity = capacity;
}
@JsonView(Notification.CNView.class)
public Booking getBooking() {
return booking;
}
public void setBooking(Booking booking) {
this.booking = booking;
}
@JsonView(AlertView.class)
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
@JsonView(CNView.class)
public List<String> getDevices() {
return devices;
}
public void setDevices(List<String> devices) {
this.devices = devices;
}
@JsonView(CNView.class)
public List<String> getRoomImages() {
return roomImages;
}
public void setRoomImages(List<String> roomImages) {
this.roomImages = roomImages;
}
@JsonView(Notification.CNView.class)
public List<Attendees> getAttendees() {
return attendees;
}
public void setAttendees(List<Attendees> attendees) {
this.attendees = attendees;
}
}
3、在Controller方法上指定视图
在完成上面两步后,只需在Controller方法上使用@JsonView注解声明需要向前端返回的视图即可,如果不声明视图则会忽略类中的注解,返回所有的字段。如下:
@JsonView(Notification.AlertView.class)
@RequestMapping(value = "/testSendN",method = RequestMethod.GET)
public Notification testSendNotification()
{
List<String> roomImages=new ArrayList<String>();
String roomImage=new String("https://www.jsjzx.top/Volunteer/Images/20.1.jpg");
roomImages.add(roomImage);
String protrait=new String("https://www.jsjzx.top/Volunteer/Images/b.jpg");
List<String> devices=new ArrayList<String>();
devices.add("麦克风");
devices.add("投影仪");
String routine=new String("https://www.jsjzx.top/Volunteer/Images/tt.png");
String goods=new String("https://www.jsjzx.top/Volunteer/Images/2a.jpg");
Booking booking=new Booking(BigInteger.valueOf(2),goods,"柠檬水",8,5);
List<Attendees> attendees=new ArrayList<Attendees>();
Attendees attendee1=new Attendees();
attendee1.setName("陆凝丹");
attendee1.setUri("https://www.jsjzx.top/Volunteer/Images/a.jpg");
Attendees attendee2=new Attendees();
attendee2.setUri("https://www.jsjzx.top/Volunteer/Images/b.jpg");
attendee2.setName("付初露");
attendees.add(attendee1);
attendees.add(attendee2);
Notification notification=new Notification();
notification.setId(BigInteger.valueOf(2));
notification.setAddress("浙江省杭州市拱墅区祥园路99号");
notification.setCapacity(20);
notification.setCompany("运河广告产业大厦");
notification.setDetail("更简洁");
notification.setHolder("陆凝丹");
notification.setInstruction("不可损坏设备");
notification.setLatitude("30.3368799267");
notification.setLongitude("120.1175165193");
notification.setRead(false);
notification.setReason("由于设备故障导致会议室暂时无法使用,很抱歉给您造成困扰,现已经为您更换了会议室,以下为会议室详细信息");
notification.setRoomId("D05");
notification.setTime("2019年6月14日9:00");
notification.setType(2);
notification.setRoomImages(roomImages);
notification.setProtrait(protrait);
notification.setDevices(devices);
notification.setImage(routine);
notification.setBooking(booking);
notification.setAttendees(attendees);
return notification;
}
4、查看是否完成预期效果
@JsonView(Notification.AlertView.class)的结果如下
@JsonView(Notification.CNView.class)的结果如下:
@JsonView(Notification.MNView.class)的结果如下:
比CNView多了reason字段
二、一些隐蔽的注意事项
- Controller 根据声明的视图来过滤字段,在过滤如果在类中有一些属性声明了视图,有一些没有,则没有声明视图的属性会被过滤掉,不会返回给前端
- 如果将声明视图的类作为另外一个类的属性,则在controller方法上声明的视图将失效,返回的数据为空。举个例子:如果重新声明一个CommonResult类,Notification作为它的一个属性,如下:
` @JsonView(Notification.MNView.class)
@RequestMapping(value = "/testSendN",method = RequestMethod.GET)
public CommonResult testSendNotification()
{
CommonResult result=new CommonResult();
Notification notification=appointmentService.sendNotification(BigInteger.valueOf(2));
result.setData(notification);
return result;
}`
则此时返回给前端的数据为空:
原因是在CommonResult中没有找到@JsonView所声明的视图,所以全部被过滤掉了,所以解决方法是在CommonResult中也声明同样的视图,但这样就增加了CommonResult与视图所在类的耦合。但在有些时候我们希望一些类是为整个项目服务的,所以这样的方法就不适用了,除非你声明一个全局的View接口,项目中所有的视图都用全局的view进行声明。
-
在声明视图的类中如果有其他自定义的类为属性且该属性类没有声明相同的视图,则改属性会被过滤掉,举个例子,在上述Notification类中的booking属性及attendees属性均为自定义的类,且booking属性上声明了CNView视图,但如果在Booking类中各项属性没有声明同样的视图,则booking属性会被过滤掉,如下:
可以看到booking属性是空的。
解决方法是在Booking类中加入相同的视图注解,如下:
public class Booking implements Serializable {
private static final long serialVersionUID = 1290811415389745003L;
private BigInteger id;
private String image;
private String title;
private double price;
private Integer count;
public Booking() {
}
public Booking(BigInteger id, String image, String title, double price, Integer count) {
this.id = id;
this.image = image;
this.title = title;
this.price = price;
this.count = count;
}
@JsonView(Notification.CNView.class)
public BigInteger getId() {
return id;
}
public void setId(BigInteger id) {
this.id = id;
}
@JsonView(Notification.CNView.class)
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
@JsonView(Notification.CNView.class)
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@JsonView(Notification.CNView.class)
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@JsonView(Notification.CNView.class)
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
}