Выборочно @JsonIgnore методы доступа Immutables, ТОЛЬКО во время сериализации или десериализации с использованием Джексона - PullRequest
2 голосов
/ 03 мая 2019

Это определенно не дубликат Только с использованием @JsonIgnore во время сериализации, но не десериализации . Проблема та же, но в контексте Immutables .

Когда модель (DTO / DAO) оформлена как неизменяемая, я не могу выборочно @JsonIgnore одно из свойств во время сериализации. Предположим, что у нас есть 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) и определите только метод обычного установщика ... и т. Д.

Если я попытаюсь использовать тот же метод доступа 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 как к получателю, так и к установщику, как показано ниже.

@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 в сеттер.

Документация не сильно поможет. В их Вещи, которые нужно знать о разделе, он просто упоминает следующее относительно @JsonIgnore

Если вы используете @JsonIgnore, вы должны явно указать атрибут необязательный. В неизменяемых атрибутах можно объявить как не обязательно через @Nullable, Optional или @ Value.Default, которые все различаются по своему действию, и мы ничего не получаем автоматически.

Использование @Nullable или Optional или @Value.Default бесполезно для таких полей, как password.

Я просмотрел список проблем на их странице GitHub, и похожая проблема была похожа, но пользователь запрашивал немного другой вариант использования, и использование @Nullable могло бы решить проблему, которая не работает в моем случае.

Я также пытался использовать один из ответов здесь . По-прежнему приводит к той же ошибке.

Похоже, это не поддерживается библиотекой Immutables. Я создал новый выпуск сам. Как только я получу отзывы пользователей о SOF, я, вероятно, создам sscce .

1 Ответ

0 голосов
/ 31 мая 2019

Мне пришлось использовать предложение, данное @benarena в этом комментарии . Однако мне пришлось явно указать атрибут значения свойства вместе с атрибутом 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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...