反序列化接收字段但序列化忽略字段:Jackson注解的灵活使用(序列化忽略父类也可)
背景:JSON序列化与反序列化的常见需求
在前后端分离的架构中,JSON作为数据交换的标准格式,通常会涉及以下场景:
- 反序列化:将客户端传来的JSON数据转换为Java对象(例如
@RequestBody
)。 - 序列化:将Java对象转换为JSON返回给客户端(例如
@ResponseBody
)。
在某些情况下,我们希望某些字段在 反序列化时允许接收数据,但在 json序列化时隐藏这些字段。例如:
- 接收用户密码用于登录,但返回用户信息时隐藏密码。
- 接收临时配置参数,但响应中无需暴露这些参数。
- 或继承了某个父类,但是序列化时不想要父类
问题:@JsonIgnore
的局限性
许多开发者会直接使用@JsonIgnore
注解,但这种方式会导致 双向忽略:
public class User {
@JsonIgnore // 反序列化和序列化时均被忽略
private String password;
}
此时,password
字段既不会出现在响应中,也无法接收请求中的值,无法满足需求。
解决方案:@JsonProperty(access = Access.WRITE_ONLY)
Jackson提供了@JsonProperty
注解的access
属性,通过Access.WRITE_ONLY
可实现 只写不读 的效果。
代码示例
public class User {
@JsonProperty(access = Access.WRITE_ONLY)
private String password;
}
注解行为
操作 | 是否生效 |
---|---|
反序列化(写) | ✅ 允许接收JSON数据 |
序列化(读) | ❌ 字段被忽略,不输出到JSON |
实战案例:处理敏感字段和临时参数
场景描述
- 接收用户注册请求,包含敏感字段(如密码)。
- 返回用户信息时,需隐藏敏感字段。
实体类定义
public class UserDTO {
private String username;
@JsonProperty(access = Access.WRITE_ONLY)
private String password;
// Getters & Setters
}
请求与响应
输入JSON(反序列化)
{
"username": "john_doe",
"password": "securePassword123"
}
输出JSON(序列化)
{
"username": "john_doe"
// password字段被自动隐藏
}
高级用法:嵌套对象的字段控制
若需要处理嵌套对象的字段,@JsonProperty(access)
同样适用。
示例代码
public class Order {
private String orderId;
@JsonProperty(access = Access.WRITE_ONLY)
private String internalSecret;
@Valid
private User user;
}
public class User {
@JsonProperty(access = Access.WRITE_ONLY)
private String tempToken;
}
请求与响应
输入JSON
{
"orderId": "ORDER_123",
"internalSecret": "SECRET_XYZ",
"user": {
"tempToken": "TEMP_123"
}
}
输出JSON
{
"orderId": "ORDER_123",
"user": {} // tempToken被隐藏
}
合理利用Jackson注解,可以轻松实现 反序列化接收字段 和 序列化忽略字段 的精细化控制,提升API安全性以及自定义。