在实际的开发过程中,我们经常会遇到这样的场景:后端 API 需要返回给前端的数据对象 Bean 中,某些字段我们并不希望序列化(展示)出去,或者希望在接收前端数据时,忽略某些字段的反序列化。Spring Boot 提供了强大的机制来对 Bean 的属性序列化和反序列化进行精细化控制,避免无效字段的传输,提升系统性能和安全性。
问题场景重现:用户信息敏感字段泄露风险
假设我们有一个 User 类,包含了用户的姓名、年龄、性别、身份证号等信息。在提供用户信息的 API 接口中,我们不希望将身份证号等敏感信息暴露给前端。如果直接将 User 对象序列化成 JSON 返回,就会存在信息泄露的风险。
public class User {
private String name;
private int age;
private String gender;
private String idCard;
// 省略 getter 和 setter 方法
}
底层原理深度剖析:Jackson 注解与配置
Spring Boot 默认使用 Jackson 库进行 JSON 序列化和反序列化。Jackson 提供了丰富的注解和配置选项,可以对 Bean 的属性进行精细化控制。
@JsonIgnore: 忽略该字段的序列化和反序列化。@JsonIgnoreProperties: 忽略类中指定的多个字段的序列化和反序列化。可以设置ignoreUnknown = true来忽略反序列化时 JSON 中存在但 Bean 中不存在的字段,防止报错。@JsonInclude: 控制哪些属性会被序列化。常用的属性有Include.NON_NULL(只序列化非 null 的属性)、Include.NON_EMPTY(只序列化非 null 且非空的属性)。@JsonProperty: 指定序列化和反序列化时使用的字段名。可以解决前后端字段名不一致的问题。@JsonSerialize和@JsonDeserialize: 用于自定义序列化器和反序列化器,可以实现更复杂的控制逻辑。
代码解决方案:多种注解灵活使用
针对上述用户信息泄露的场景,我们可以使用 @JsonIgnore 注解来忽略 idCard 字段的序列化:
import com.fasterxml.jackson.annotation.JsonIgnore;
public class User {
private String name;
private int age;
private String gender;
@JsonIgnore // 忽略 idCard 字段的序列化
private String idCard;
// 省略 getter 和 setter 方法
}
如果我们希望在接收前端数据时,忽略某些前端传递的冗余字段,可以使用 @JsonIgnoreProperties(ignoreUnknown = true):
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true) // 忽略 JSON 中存在但 Bean 中不存在的字段
public class User {
private String name;
private int age;
private String gender;
private String idCard;
// 省略 getter 和 setter 方法
}
另外,使用 @JsonInclude(Include.NON_NULL) 可以避免返回给前端过多的 null 字段,减小数据包大小:
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
@JsonInclude(Include.NON_NULL) // 只序列化非 null 的属性
public class User {
private String name;
private Integer age; // 使用 Integer 类型,允许为 null
private String gender;
private String idCard;
// 省略 getter 和 setter 方法
}
对于前后端字段名不一致的情况,可以使用 @JsonProperty 进行映射:
import com.fasterxml.jackson.annotation.JsonProperty;
public class User {
@JsonProperty("userName") // 将 name 字段映射为 userName
private String name;
private int age;
private String gender;
private String idCard;
// 省略 getter 和 setter 方法
}
实战避坑经验总结:Jackson 版本兼容与配置优先级
- Jackson 版本兼容性: 不同版本的 Jackson 库,注解的行为可能存在差异,需要注意版本兼容性问题。建议使用 Spring Boot 提供的 Jackson 版本管理,避免版本冲突。
- 配置优先级: Jackson 的配置可以通过注解、配置文件、自定义
ObjectMapper等方式进行。需要注意配置的优先级,避免配置冲突导致结果不符合预期。例如,application.properties中可以通过spring.jackson.*属性来配置 Jackson 的行为。 - 自定义序列化器: 对于复杂的序列化和反序列化逻辑,可以自定义
JsonSerializer和JsonDeserializer,实现更灵活的控制。例如,可以对日期格式进行自定义,或者对敏感信息进行加密处理。
通过 Bean 属性序列化反序列化 的精细化控制,我们可以有效地保护敏感信息,提升系统性能,并提高代码的可维护性。在实际开发中,根据具体的业务场景选择合适的注解和配置方式,才能更好地发挥 Jackson 的强大功能。
冠军资讯
代码一只喵