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


163

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

class User {
    private String password;

    //setter, getter..
}

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

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


1
Вы не хотите сериализовать это, но вы хотите быть в состоянии десериализовать это? Это невозможно, я бы сказал. Если вы не поместите куки в ящик, вы не сможете получить его из этого ящика.
— Алексис Дафреной

1
@Traroth: но я могу поставить новое печенье. Я просто ищу удобную аннотацию, но это наверняка можно сделать вручную.
— Weekens

8
Краткий комментарий: технически вполне возможно иметь используемый установщик (даже закрытые автоматически распознаются) и просто пропустить средство доступа (без открытого поля или получателя). Также возможно добавить @JsonIgnoreна getter, но @JsonPropertyна setter, в этом случае вещи не сериализуются, но могут быть десериализованы.
— StaxMan

4
Не могли бы вы принять ответ на этот вопрос? (Парочке ваших других несколько лет, и они все еще не приняты ... Пожалуйста, рассмотрите обзор!) :) Полное раскрытие - у меня нет ответов на любые из этих вопросов.
— Баретт

Ответы:


187

Вы можете пометить это как @JsonIgnore.

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


6
@JsonIgnore также предотвращает десериализацию. Для переходного процесса - я проверю это.
— Weekens

98
С 1.9 вы можете добавить @JsonIgnoreдля getter, @JsonPropertyдля setter, чтобы десериализовать, но не сериализовать.
— StaxMan

Ответ StaxMan должен быть ответом, не так ли? Почему это все еще комментарий тогда ...! ..?
— Сараванабалаги Рамачандран

переходный процесс, кажется, не работает для меня, я отметил поле «переходный процесс», что я не хочу, чтобы его сериализовали / десериализовали.
— Рохит

В этом ответе ранее предлагалось использовать transient(как в private transient String password;), но переходные поля с общедоступными получателями игнорируются, если не включен MapperFeature.PROPAGATE_TRANSIENT_MARKER .
— Том

96

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

private String password;

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

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

12
Какую зависимость от Json вы используете? Это не работает с com.fasterxml.jackson
— Александр Буракевич

3
Спасибо! @JsonIgnoreне нужно на поле, кажется.
— Ферран Майлинч

com.fasterxml.jackson.annotation.JsonIgnore from jackson-annotations- <версия> .jar
— mvmn

Я попробовал это, и это не работает для меня. Я использую v2.8. Любая помощь?
— Маз

36

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

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

class User {

    private String password;

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

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

    @JsonProperty("password")
    public String getEncryptedPassword() {
        // encryption logic
    }
}

21

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

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

Это отличное решение, простое, работающее. Спасибо.
— dhqvinh

17

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

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

10

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


2
Это сработает, если ваш атрибут действительно временный, например, без участия ORM .... В моем случае @JsonIgnore оказался более интересным, хотя я был бы привязан к Джексону, но это хороший компромисс
— Жоао Перейра

3
Вам не нужно быть привязанным к Джексону, если вы создаете собственную аннотацию и аннотируете ее JsonIgnore и JacksonAnnotationsInside. Таким образом, если вы меняете сериализаторы, вам нужно только изменить собственную аннотацию.
— DavidA

4

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

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

Я на самом деле думаю, что это лучший способ думать о решении. Имеет больше смысла делать вещи, которые вам нужны, приватными и контролировать их с самого объекта.
— arcynum

2

У Джексона есть класс 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

0

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

@JsonIgnore

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.