选择性地@JsonIgnore Immutables 访问器方法,仅在使用 Jackson 进行序列化或反序列化期间
Selectively @JsonIgnore Immutables accessor methods, ONLY during serialization or deserialization using Jackson
这绝对不是 Only using @JsonIgnore during serialization, but not deserialization. The problem is the same but in the context of Immutables 的重复。
当模型 (DTO/DAO) 被装饰为不可变对象时,我无法在序列化期间有选择地 @JsonIgnore 属性之一。假设我们有一个 UserDto,它被定义为一个 Immutable,如下所示
@Value.Immutable
@Value.Style(defaults = @Value.Immutable(copy = false), init = "set*")
@JsonSerialize(as = ImmutableUserDto.class)
@JsonDeserialize(builder = ImmutableUserDto.Builder.class)
public abstract class UserDto {
@JsonProperty("id")
@Value.Default
public int getId() {
return 0;
}
@JsonProperty("username")
public abstract String getUsername();
@JsonProperty("email")
public abstract String getEmail();
@JsonProperty("password")
public abstract String getPassword();
}
我认为在序列化期间我们希望忽略服务响应中的 password
是公平的。
如果我们使用的是一个简单的 class,那么在不使用 Immutable 的情况下,有很多方法可以实现这一点。例如 - 仅使用 @JsonIgnore
注释 getter。或者,如果可能的话,定义一个不同的访问器方法(没有 get 前缀的东西)并且只定义常规的 setter 方法......等等。
如果我在 Immutables 访问器方法上尝试相同的密码,如下所示:
@Value.Immutable
@Value.Style(defaults = @Value.Immutable(copy = false), init = "set*")
@JsonSersonIgnoreialize(as = ImmutableUserDto.class)
@JsonDeserialize(builder = ImmutableUserDto.Builder.class)
public abstract class UserDto {
....
@JsonProperty("password")
@JsonIgnore
public abstract String getPassword();
}
然后,生成的 ImmutableUserDto 在 getter 和 setter 上添加 @JsonIgnore,如下所示。
@Generated(from = "UserDto", generator = "Immutables")
@SuppressWarnings({"all"})
@ParametersAreNonnullByDefault
@javax.annotation.Generated("org.immutables.processor.ProxyProcessor")
@Immutable
@CheckReturnValue
public final class ImmutableUserDto extends UserDto {
...
...
private final String password;
...
...
/**
* @return The value of the {@code password} attribute
*/
@JsonProperty("password")
@JsonIgnore
@Override
public String getPassword() {
return password;
}
...
...
...
@Generated(from = "UserDto", generator = "Immutables")
@NotThreadSafe
public static final class Builder {
...
...
private String password;
@JsonProperty("password")
@JsonIgnore
public final Builder setPassword(String password) {
this.password = password;
return this;
}
}
}
序列化将按预期进行。 password
属性将从 JSON 中排除。但是当我尝试反序列化时,出现以下错误:
java.lang.IllegalStateException: Cannot build UserDto, some of the required attributes are not set [password]
这很明显,因为 Immutables 也将 @JsonIgnore
添加到 setter。
documentation 没有太大帮助。在他们的 Things to be aware of 部分中,它只是提到以下关于 @JsonIgnore
If using @JsonIgnore, you should explicitly make an attribute
non-mandatory. In Immutables, an attribute can be declared as
non-mandatory via @Nullable, Optional or @Value.Default which are all
different in their effect and we do not derive anything automatically.
使用 @Nullable
或 Optional
或 @Value.Default
对于 password
.
这样的字段没有任何用处
我已经浏览了他们 GitHub 页面上的问题列表并且有一个 similar issue 但是用户要求一个稍微不同的用例并且使用 @Nullable 可以解决这个问题在我的情况下工作。
我也试过使用其中一个答案here。仍然导致相同的错误。
Immutables 库似乎不支持此功能。我创建了一个 new issue myself. Once I get some feedback from users on SOF, I will probably create a sscce.
我不得不在这个 中使用@benarena 给出的建议。但是,我必须明确指定 属性 的 value 属性以及 Access 属性。
@JsonProperty(value = "password", access = JsonProperty.Access.WRITE_ONLY)
解决了问题。
不可变 class 看起来像:
@Value.Immutable
@Value.Style(defaults = @Value.Immutable(copy = false), init = "set*")
@JsonSersonIgnoreialize(as = ImmutableUserDto.class)
@JsonDeserialize(builder = ImmutableUserDto.Builder.class)
public abstract class UserDto {
....
@JsonProperty(value = "password", access = JsonProperty.Access.WRITE_ONLY)
public abstract String getPassword();
}
这绝对不是 Only using @JsonIgnore during serialization, but not deserialization. The problem is the same but in the context of Immutables 的重复。
当模型 (DTO/DAO) 被装饰为不可变对象时,我无法在序列化期间有选择地 @JsonIgnore 属性之一。假设我们有一个 UserDto,它被定义为一个 Immutable,如下所示
@Value.Immutable
@Value.Style(defaults = @Value.Immutable(copy = false), init = "set*")
@JsonSerialize(as = ImmutableUserDto.class)
@JsonDeserialize(builder = ImmutableUserDto.Builder.class)
public abstract class UserDto {
@JsonProperty("id")
@Value.Default
public int getId() {
return 0;
}
@JsonProperty("username")
public abstract String getUsername();
@JsonProperty("email")
public abstract String getEmail();
@JsonProperty("password")
public abstract String getPassword();
}
我认为在序列化期间我们希望忽略服务响应中的 password
是公平的。
如果我们使用的是一个简单的 class,那么在不使用 Immutable 的情况下,有很多方法可以实现这一点。例如 - 仅使用 @JsonIgnore
注释 getter。或者,如果可能的话,定义一个不同的访问器方法(没有 get 前缀的东西)并且只定义常规的 setter 方法......等等。
如果我在 Immutables 访问器方法上尝试相同的密码,如下所示:
@Value.Immutable
@Value.Style(defaults = @Value.Immutable(copy = false), init = "set*")
@JsonSersonIgnoreialize(as = ImmutableUserDto.class)
@JsonDeserialize(builder = ImmutableUserDto.Builder.class)
public abstract class UserDto {
....
@JsonProperty("password")
@JsonIgnore
public abstract String getPassword();
}
然后,生成的 ImmutableUserDto 在 getter 和 setter 上添加 @JsonIgnore,如下所示。
@Generated(from = "UserDto", generator = "Immutables")
@SuppressWarnings({"all"})
@ParametersAreNonnullByDefault
@javax.annotation.Generated("org.immutables.processor.ProxyProcessor")
@Immutable
@CheckReturnValue
public final class ImmutableUserDto extends UserDto {
...
...
private final String password;
...
...
/**
* @return The value of the {@code password} attribute
*/
@JsonProperty("password")
@JsonIgnore
@Override
public String getPassword() {
return password;
}
...
...
...
@Generated(from = "UserDto", generator = "Immutables")
@NotThreadSafe
public static final class Builder {
...
...
private String password;
@JsonProperty("password")
@JsonIgnore
public final Builder setPassword(String password) {
this.password = password;
return this;
}
}
}
序列化将按预期进行。 password
属性将从 JSON 中排除。但是当我尝试反序列化时,出现以下错误:
java.lang.IllegalStateException: Cannot build UserDto, some of the required attributes are not set [password]
这很明显,因为 Immutables 也将 @JsonIgnore
添加到 setter。
documentation 没有太大帮助。在他们的 Things to be aware of 部分中,它只是提到以下关于 @JsonIgnore
If using @JsonIgnore, you should explicitly make an attribute non-mandatory. In Immutables, an attribute can be declared as non-mandatory via @Nullable, Optional or @Value.Default which are all different in their effect and we do not derive anything automatically.
使用 @Nullable
或 Optional
或 @Value.Default
对于 password
.
我已经浏览了他们 GitHub 页面上的问题列表并且有一个 similar issue 但是用户要求一个稍微不同的用例并且使用 @Nullable 可以解决这个问题在我的情况下工作。
我也试过使用其中一个答案here。仍然导致相同的错误。
Immutables 库似乎不支持此功能。我创建了一个 new issue myself. Once I get some feedback from users on SOF, I will probably create a sscce.
我不得不在这个
@JsonProperty(value = "password", access = JsonProperty.Access.WRITE_ONLY)
解决了问题。
不可变 class 看起来像:
@Value.Immutable
@Value.Style(defaults = @Value.Immutable(copy = false), init = "set*")
@JsonSersonIgnoreialize(as = ImmutableUserDto.class)
@JsonDeserialize(builder = ImmutableUserDto.Builder.class)
public abstract class UserDto {
....
@JsonProperty(value = "password", access = JsonProperty.Access.WRITE_ONLY)
public abstract String getPassword();
}