仅在序列化时使用 @JsonIgnore,反序列化时不使用
技术背景
在开发过程中,我们经常需要处理对象的序列化和反序列化,尤其是在前后端数据交互时。例如,在处理用户对象时,为了保证数据安全,我们不希望在将用户对象发送到客户端时包含用户的密码信息,但在接收客户端发送的注册信息时,又需要将密码反序列化到对象中。@JsonIgnore
注解可以用来忽略某些属性的序列化和反序列化,但默认情况下它会同时影响这两个过程,因此需要找到一种方法让它仅在序列化时生效。
实现步骤
方法一:旧版本 Jackson(1.9 及以前)
在旧版本的 Jackson 中,可以通过在 getter 方法上添加 @JsonIgnore
注解,并在 setter 方法上添加 @JsonProperty
注解来实现仅在序列化时忽略属性。
示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class User { private String password;
@JsonIgnore public String getPassword() { return password; }
@JsonProperty public void setPassword(final String password) { this.password = password; } }
|
方法二:新版本 Jackson(2.6 及以后)
从 Jackson 2.6 版本开始,可以使用 @JsonProperty
注解的 access
属性来更直观地控制属性的序列化和反序列化。通过设置 access = Access.WRITE_ONLY
,可以让属性仅在反序列化时使用,序列化时忽略。
示例代码如下:
1 2 3 4 5 6 7 8 9
| import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty.Access;
class User { @JsonProperty(access = Access.WRITE_ONLY) private String password;
}
|
方法三:使用 @JsonIgnoreProperties
注解
可以在类级别使用 @JsonIgnoreProperties
注解,并设置 allowSetters = true
来允许属性在反序列化时被设置,但在序列化时忽略。
示例代码如下:
1 2 3 4 5 6 7 8
| import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(allowSetters = true, value = {"password"}) class User { private String password;
}
|
核心代码
以下是使用 @JsonProperty(access = Access.WRITE_ONLY)
方法的完整示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty.Access; import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
class User { private String username; @JsonProperty(access = Access.WRITE_ONLY) private String password;
public User(String username, String password) { this.username = username; this.password = password; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; } }
public class Main { public static void main(String[] args) throws IOException { ObjectMapper objectMapper = new ObjectMapper();
User user = new User("john_doe", "secret_password"); String json = objectMapper.writeValueAsString(user); System.out.println("Serialized JSON: " + json);
String jsonInput = "{\"username\":\"jane_smith\",\"password\":\"new_password\"}"; User deserializedUser = objectMapper.readValue(jsonInput, User.class); System.out.println("Deserialized User: " + deserializedUser.getUsername() + ", " + deserializedUser.getPassword()); } }
|
最佳实践
- 版本兼容性:根据使用的 Jackson 版本选择合适的方法。如果是较新的项目,建议使用
@JsonProperty(access = Access.WRITE_ONLY)
方法,因为它更简洁直观。 - 注解导入:确保导入的是正确的注解类,例如
com.fasterxml.jackson.annotation.JsonProperty
和 com.fasterxml.jackson.annotation.JsonProperty.Access
,避免使用错误的包导致注解不生效。 - 代码可读性:在代码中添加必要的注释,解释每个注解的作用,提高代码的可读性和可维护性。
常见问题
@JsonIgnore
注解不生效
可能是因为导入了错误的注解类,例如 org.codehaus.jackson.annotate.JsonIgnore
,应该使用 com.fasterxml.jackson.annotation.JsonIgnore
。
@JsonProperty(access = Access.WRITE_ONLY)
不生效
检查是否存在其他注解覆盖了该注解的设置,例如在字段上同时使用了 @JsonProperty
注解且没有正确设置 access
属性。另外,确保使用的是 Jackson 2.6 及以上版本。