在SpringBoot中使用Jackson过滤不必要字段

在开发接口的时候,我们通常想要过滤一些字段不返回给前端。

例如前端需要查询一个用户,但是用户User类中通常有密码字段,我们不想返回密码字段给前端,应当怎么办呢?使用Jackson依赖即可完美解决。

不过首先我们需要了解一些基本知识。

1,什么是序列化/反序列化

我们前后端交互的对象都需要使用Serializable接口,表示这个类的实例是可以序列化和反序列化的。

Java的实例一般存在于内存里面,如果想要把这个对象在网络上传输或者是存放到本地,那么必须要使这个对象序列化,也就是说序列化把一个内存中的对象数据转换为了可传输存储的形式,例如字符串等等。

在Spring Boot中,通常前端会以JSON格式把对象传给后端(例如用户登录,前端把用户信息组装为JSON传给后端,后端解析为User对象),后端(Spring Boot)会将这个JSON解析为对象/实例,这就是反序列化的过程。(JSON字符串->Java对象

以及前端有时需要发送请求向后端查询对象(例如前端查户列表),这时后端接收了请求就会去数据库查询,查询到的数据组装为Java对象,然后再把这些Java对象转换为JSON字符串形式返回给前端,这就是序列化过程。(Java对象->JSON字符串

序列化和反序列化不止这些,上面只是简要地说了在Spring Boot中常见的对象传输方式。我们只需了解这些即可。

2,配置Jackson过滤一些不必要字段

首先配置Maven依赖,在dependencies加入:

<dependency>
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-annotations</artifactId>
   <version>2.13.0</version>
</dependency>
复制代码

然后使用注解来过滤不需要的字段。

例如User类中,我们可以使用@JsonIgnore注解来忽略掉某些字段,这个注解标注于类的属性上,例如:

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
 
import java.io.Serializable;
 
/**
 * 用户
 */
@Getter
@Setter
@NoArgsConstructor
public class User implements Serializable {
 
	/**
	 * id
	 */
	private int id;
 
	/**
	 * 用户名
	 */
	private String username;
 
	/**
	 * 用户密码,32位MD5加密储存,小写
	 */
	@JsonIgnore
	private String pwd;
 
}
复制代码

可见pwd密码字段上面标注了@JsonIgnore,这样序列化和反序列化都会忽略pwd字段。

问题来了,这样确实解决了前端查询用户时过滤掉密码字段,但是前端发送用户信息(用户登录注册时)后端反序列化时也过滤了密码字段。

其实我们通常更多使用@JsonIgnoreProperties注解,这个注解更强大,它标注于类上面,它有如下属性:

  • value 字段名,值为数组,表示要过滤的字段
  • ignoreUnknown 忽略未知属性,配置为true则会忽略未知属性,默认不忽略
  • allowGetters 允许忽略字段被序列化,默认不允许。配置为true时,上述配置为要过滤的字段也会被序列化
  • allowSetters 忽略字段被反序列化,默认不允许。配置为true时,上述配置为要过滤的字段也会被反序列化

对于上述User类,我们需要在用户登录注册(即前端传送数据给后端)时后端仍要对pwd字段进行读取和反序列化,而前端查询用户时(后端返回数据给前端)过滤掉pwd字段,通过@JsonIgnoreProperties配置如下:

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
 
import java.io.Serializable;
 
/**
 * 管理员用户
 */
@Getter
@Setter
@NoArgsConstructor
@JsonIgnoreProperties(allowSetters = true, value = {"pwd"})
public class User implements Serializable {
 
	/**
	 * id
	 */
	private int id;
 
	/**
	 * 用户名
	 */
	private String username;
 
	/**
	 * 用户密码,32位MD5加密储存,小写
	 */
	private String pwd;
 
}
复制代码

可见我们注解中配置过滤pwd字段,并允许这个字段被反序列化。这样就实现了仅仅不传输密码字段给前端。