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

163

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

class User {
    private String password;

    //setter, getter..
}

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

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

weekens
источник
1
Вы не хотите сериализовать это, но вы хотите быть в состоянии десериализовать это? Это невозможно, я бы сказал. Если вы не поместите куки в ящик, вы не сможете получить его из этого ящика.
Алексис Дафреной
1
@Traroth: но я могу поставить новое печенье. Я просто ищу удобную аннотацию, но это наверняка можно сделать вручную.
Weekens
8
Краткий комментарий: технически вполне возможно иметь используемый установщик (даже закрытые автоматически распознаются) и просто пропустить средство доступа (без открытого поля или получателя). Также возможно добавить @JsonIgnoreна getter, но @JsonPropertyна setter, в этом случае вещи не сериализуются, но могут быть десериализованы.
StaxMan
4
Не могли бы вы принять ответ на этот вопрос? (Парочке ваших других несколько лет, и они все еще не приняты ... Пожалуйста, рассмотрите обзор!) :) Полное раскрытие - у меня нет ответов на любые из этих вопросов.
Баретт

Ответы:

187

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

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

Biju Kunjummen
источник
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;
}
Gary
источник
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 на уроке может быть полезно
StaxMan
источник
10

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

maxxyme
источник
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
krhitesh
источник
0

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

@JsonIgnore

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

Pravin
источник