Джексон: как предотвратить полевую сериализацию

У меня есть класс сущности с полем пароля:

class User {
    private String password;

    //setter, getter..
}

Я хочу, чтобы это поле было пропущено во время сериализации. Но он все еще должен быть в состоянии DEserialize. Это необходимо, чтобы клиент мог отправить мне новый пароль, но не смог прочитать текущий.

Как мне сделать это с Джексоном?

9 ответов

Вы можете пометить его как @JsonIgnore,

С 1.9 вы можете добавить @JsonIgnore для добытчика, @JsonProperty для сеттера, чтобы сделать его десериализованным, но не сериализованным.

Иллюстрируя сказанное StaxMan, это работает для меня

private String password;

@JsonIgnore
public String getPassword() {
    return password;
}

@JsonProperty
public void setPassword(String password) {
    this.password = password;
}

Начиная с Jackson 2.6, свойство может быть помечено как доступное только для чтения или записи. Это проще, чем взломать аннотации на обоих средствах доступа и хранить всю информацию в одном месте:

public class User {
    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    private String password;
}

Самый простой способ - комментировать ваши методы получения и установки.

Вот оригинальный пример, измененный, чтобы исключить простой текстовый пароль, но затем аннотировать новый метод, который просто возвращает поле пароля в виде зашифрованного текста.

class User {
    private String password;

    public void setPassword(String password){...}
    @JsonIgnore
    public String getPassword(){...}

    @JsonProperty("password"}
    public String getEncryptedPassword(){...}
}

Помимо @JsonIgnoreЕсть несколько других возможностей:

  • Используйте JSON Views для условной фильтрации полей (по умолчанию не используется для десериализации; в 2.0 будет доступно, но вы можете использовать другое представление для сериализации, десериализации)
  • @JsonIgnoreProperties на уроке может быть полезно

transient это решение для меня. Спасибо! он является родным для Java и не требует добавления другой аннотации, специфичной для фреймворка.

Джексон имеет класс с именем SimpleBeanPropertyFilter, который помогает фильтровать поля во время сериализации и десериализации; не глобально. Я думаю, это то, что вы хотели.

@JsonFilter("custom_serializer")
class User {
    private String password;

    //setter, getter..
}

Тогда в вашем коде:

String[] fieldsToSkip = new String[] { "password" };

ObjectMapper mapper = new ObjectMapper();

final SimpleFilterProvider filter = new SimpleFilterProvider();
filter.addFilter("custom_serializer",
            SimpleBeanPropertyFilter.serializeAllExcept(fieldsToSkip));

mapper.setFilters(filter);

String jsonStr = mapper.writeValueAsString(currentUser);

Это предотвратит password поле для сериализации. Также вы сможете десериализовать password поля как есть. Просто убедитесь, что фильтры не применяются к объекту ObjectMapper.

ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(yourJsonStr, User.class);    // user object does have non-null password field

Следует спросить, зачем вам нужен публичный метод получения пароля. Hibernate, или любая другая платформа ORM, будет делать с частным методом получения. Для проверки правильности пароля вы можете использовать

public boolean checkPassword(String password){
  return this.password.equals(anyHashingMethod(password));
}

Установить переменную как

@JsonIgnore

Это позволяет переменной быть пропущенным сериализатором json

Другие вопросы по тегам