仅在序列化时使用 @JsonIgnore,反序列化时不使用

仅在序列化时使用 @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 {
// More fields here
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;

// getters and setters
}

方法三:使用 @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;

// getters and setters
}

核心代码

以下是使用 @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.JsonPropertycom.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 及以上版本。


仅在序列化时使用 @JsonIgnore,反序列化时不使用
https://119291.xyz/posts/2025-04-22.only-use-jsonignore-during-serialization/
作者
ww
发布于
2025年4月22日
许可协议