选择性@JsonIgnore不可变访问器方法,仅在使用Jackson进行序列化或反序列化期间

时间:2019-05-03 07:42:17

标签: java jackson jackson-databind immutables-library

这绝对不是Only using @JsonIgnore during serialization, but not deserialization的副本。问题是相同的,但是在Immutables的上下文中。

当将模型(DTO / DAO)装饰为不可变时,我无法在序列化期间有选择地@JsonIgnore其中一个属性。假设我们有一个定义为Immutable的UserDto,如下所示:

@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

如果我们使用的是简单类,则无需使用Immutables,那么有很多方法可以实现这一点。例如-用@JsonIgnore仅注释吸气剂。或者,如果可能,请定义其他访问器方法(没有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将@JsonIgnore添加到getter和setter上,如下所示。

@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并没有太大帮助。在他们的注意事项部分中,它仅提及以下有关@JsonIgnore

的内容
  

如果使用@JsonIgnore,则应显式创建一个属性   非强制性。在不可变项中,可以将属性声明为   通过@ Nullable,Optional或@ Value.Default都是非强制性的   效果不同,我们不会自动得出任何结果。

@Nullable之类的字段中,使用Optional@Value.Defaultpassword毫无用处。

我已经在他们的GitHub页面上浏览了问题列表,并且有一个similar issue ,但是用户要求的用例略有不同,使用@Nullable可以解决在我的情况下不起作用的问题

我还尝试使用答案here之一。仍然导致相同的错误。

Immutables库似乎不支持此功能。我自己创建了一个new issue。一旦收到用户对SOF的反馈,我可能会创建一个sscce

1 个答案:

答案 0 :(得分:0)

在这个comment中,我不得不使用@benarena给出的建议。但是,我必须明确指定属性的value属性以及Access属性。

@JsonProperty(value = "password", access = JsonProperty.Access.WRITE_ONLY)解决了这个问题。

不可变类如下:

@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();
}