@JsonView
的使用场景
在某一些请求返回的JSON
中,我们并不希望返回某些字段。而在另一些请求中需要返回某些字段。
例如有如下用户对象:
public class User implements Serializable {
private Integer id;
private String username;
private String password;
}
在查询列表请求中,不返回password
字段。在获取用户详情中,返回password
字段。这时候我们就可以使用
@JsonView
注解了。
使用@JsonView
的步骤
1.使用接口来声明多个视图
2.在值对象的get方法上指定视图
3.在Controller的方法上指定视图
1、2两步的代码如下:
public class User implements Serializable {
private Integer id;
private String username;
private String password;
/**
* 1.使用接口声明多个视图
*/
public interface UserSimpleView {};
public interface UserDetailView extends UserSimpleView {};
/**
* 2.在值对象的get方法上指定视图
*/
@JsonView(UserSimpleView.class)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@JsonView(UserSimpleView.class)
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@JsonView(UserDetailView.class)
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
3步的代码如下
@RestController
public class UserController {
@Autowired
private UserService userService;
/**
* 3.在Controller方法上指定视图
*/
@RequestMapping(value = "/getuser", method = RequestMethod.GET)
@JsonView(User.UserSimpleView.class)
public List<User> queryUser(@RequestParam(value = "page", defaultValue = "0") Integer page,
@RequestParam(value = "size", defaultValue = "10") Integer size) {
PageRequest request = PageRequest.of(page, size, new Sort(Sort.Direction.DESC, "id"));
Page<User> userPage = userService.findAllUser(request);
return userPage.getContent();
}
@RequestMapping(value = "/getuser/{id}", method = RequestMethod.GET)
@JsonView(User.UserDetailView.class)
public User getUserInfo(@PathVariable Integer id) {
User user = userService.getUserById(id);
return user;
}
}
省略了一些service
、和dao
的代码。
@JsonView
无法正确应用到自己封装的ResultVo
上
实际开发过程中,我们需要自己封装返回的数据。通常我们会定义UserDto
、ResultVo
。如下:
public class UserDto implements Serializable {
private Integer id;
private String username;
private String password;
public interface UserDtoSimpleView {};
public interface UserDtoDetailView extends UserDtoSimpleView {};
@JsonView(UserDtoSimpleView.class)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@JsonView(UserDtoSimpleView.class)
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@JsonView(UserDtoDetailView.class)
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
public class ResultVo<T> implements Serializable {
private Integer code;
private String msg;
private T data;
/*省略getter、setter*/
}
此时我们在Ctroller
中使用@JsonView
,如下代码:
@RestController
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value = "/user", method = RequestMethod.GET)
@JsonView(UserDto.UserDtoSimpleView.class)
public ResultVo<Object> query(@RequestParam(value = "page", defaultValue = "0") Integer page,
@RequestParam(value = "size", defaultValue = "10") Integer size) {
PageRequest request = PageRequest.of(page, size, new Sort(Sort.Direction.DESC, "id"));
ResultVo<Object> resultVo = null;
try {
Page<UserDto> userPage = userService.findAllUserDto(request);
resultVo = ResultVoUtil.success(userPage);
} catch (Exception e) {
e.printStackTrace();
resultVo = ResultVoUtil.error();
}
return resultVo;
}
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
@JsonView(UserDto.UserDtoDetailView.class)
public ResultVo<Object> getInfo(@PathVariable Integer id) {
ResultVo<Object> resultVo = null;
try {
UserDto userDto = userService.getUserDtoById(id);
resultVo = ResultVoUtil.success(userDto);
} catch (Exception e) {
e.printStackTrace();
resultVo = ResultVoUtil.error();
}
return resultVo;
}
}
这个使用并不能返回我们预期的结果,而是返回一个空json
集合。实际上,当我们在封装了dto
之后,
我们就已经默认封装了需要返回的数据,如果没有特别的需求,没有必要一定要定义特殊的返回。
如果真的想要排除某些数据,网上有人使用JsonConfig
对象去配置。示例代码如下:
JsonConfig jc=new JsonConfig();
// 使用setExcludes方法过滤,例如我不想要对象中的roleinfo和departmentInfo:
jc.setExcludes(new String[]{"password","salt","roles","roleSet","shops","permissionsSet"});
这种方式尝试了一下,由于时代的关系…jar包不好管理。所有没能够正常实现。这里使用了com.alibaba.fastjson
。引入版本:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastJson</artifactId>
<version>1.2.7</version>
</dependency>
controller
中的代码为:
@RestController
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value = "/user", method = RequestMethod.GET)
public ResultVo<Object> query(@RequestParam(value = "page", defaultValue = "0") Integer page,
@RequestParam(value = "size", defaultValue = "10") Integer size) {
PageRequest request = PageRequest.of(page, size, new Sort(Sort.Direction.DESC, "id"));
ResultVo<Object> resultVo = null;
/**
* 1.构建排除集合
* 2.创建属性过滤对象
* 3.添加过滤集合到属性过滤对象
*/
List<String> excludes = new ArrayList<String>();
excludes.add("password");
SimplePropertyPreFilter filter = new SimplePropertyPreFilter();
filter.getExcludes().addAll(excludes);
try {
Page<UserDto> userPage = userService.findAllUserDto(request);
/**
* 1.获取排除字段后的新的json集合
* 2.生成新的排除字段值后的集合对象
* 3.构建返回对象
*/
String jsonStr = JSON.toJSONString(userPage.getContent(), filter);
List<UserDto> list = JSONObject.parseArray(jsonStr, UserDto.class);
PageImpl<UserDto> pageImpl = new PageImpl<UserDto>(
list, request, userPage.getTotalElements());
resultVo = ResultVoUtil.success(pageImpl);
} catch (Exception e) {
e.printStackTrace();
resultVo = ResultVoUtil.error();
}
return resultVo;
}
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
public ResultVo<Object> getInfo(@PathVariable Integer id) {
ResultVo<Object> resultVo = null;
try {
UserDto userDto = userService.getUserDtoById(id);
resultVo = ResultVoUtil.success(userDto);
} catch (Exception e) {
e.printStackTrace();
resultVo = ResultVoUtil.error();
}
return resultVo;
}
}
按照此方法能够正常的实现排除了密码部分的返回值,但是这里有个遗留问题,就是尽管排除了,但是在二次
构建List<UserDto>
时,引入了password
属性,所以返回值中,所有password
都是null
。
当然这个问题可以解决,但是个人不建议继续处理。
原文链接: https://marshucheng1.github.io/2017/03/11/@JsonView%E4%BD%BF%E7%94%A8/