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

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

class User {
    private String password;

    //setter, getter..
}

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

Как мне добиться этого с Джексоном?


person weekens    schedule 02.02.2012    source источник
comment
Вы не хотите сериализовать его, но хотите иметь возможность десериализовать его? Я бы сказал, это невозможно. Если вы не поместите файл cookie в ящик, вы не сможете получить его из этого ящика.   -  person Alexis Dufrenoy    schedule 02.02.2012
comment
@Traroth: но я могу поставить НОВОЕ печенье. Просто ищу удобную аннотацию, но это наверняка можно сделать своими руками.   -  person weekens    schedule 02.02.2012
comment
Быстрый комментарий: технически вполне возможно использовать сеттер (даже частные автоматически обнаруживаются) и просто опускать аксессор (без общедоступного поля или геттера). Также можно добавить @JsonIgnore в геттер, но @JsonProperty в сеттер, и в этом случае вещи не сериализуются, но могут быть десериализованы.   -  person StaxMan    schedule 03.02.2012
comment
Не могли бы вы принять ответ на этот вопрос? (Некоторым вашим другим несколько лет, и они все еще не приняты ... Пожалуйста, рассмотрите возможность пересмотра!) :) Полное раскрытие информации - у меня нет ответов ни на один из этих вопросов.   -  person Barett    schedule 10.11.2016
comment
Отвечает ли это на ваш вопрос? Использование только @JsonIgnore во время сериализации, но не десериализации   -  person kulsin    schedule 01.10.2020


Ответы (9)


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

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

person Biju Kunjummen    schedule 02.02.2012
comment
@JsonIgnore также предотвращает десериализацию. На переходный - проверю. - person weekens; 02.02.2012
comment
В версии 1.9 вы можете добавить @JsonIgnore для получателя, @JsonProperty для установщика, чтобы он десериализовался, но не сериализовался. - person StaxMan; 03.02.2012
comment
Комментарий StaxMan должен быть ответом, не так ли? Почему тогда до сих пор комментарий ...! ..? - person Saravanabalagi Ramachandran; 22.10.2015
comment
transient, похоже, не работает для меня, я отметил переходный процесс поля, который я не хочу, чтобы он был сериализован / десериализован. - person rohith; 03.03.2016
comment
В этом ответе ранее предлагалось использовать transient (как в private transient String password;), но игнорируются переходные поля с общедоступными геттерами кроме случаев, когда Mapping PROPAGATE_TRANSIENT_MARKER включен. - person tom; 12.10.2017
comment
@JsonIgnore в поле и геттере и @JsonProperty в сеттере десериализует и не сериализует единичное свойство. Однако когда я делаю то же самое в поле List ‹Foo›, оно тоже не десериализуется? Какие-нибудь решения для этого? - person Farrukh Najmi; 20.10.2017

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

private String password;

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

@JsonProperty
public void setPassword(String password) {
    this.password = password;
}
person Gary    schedule 03.10.2012
comment
Какую зависимость Json вы используете? Это не работает с com.fasterxml.jackson - person Alexander Burakevych; 21.07.2014
comment
Спасибо! @JsonIgnore на поле вроде бы не нужен. - person Ferran Maylinch; 09.08.2014
comment
com.fasterxml.jackson.annotation.JsonIgnore from jackson-annotations- ‹version› .jar - person mvmn; 06.06.2017
comment
Я пробовал это, и у меня это не работает. Пользуюсь v2.8. Любая помощь? - person Maz; 11.01.2018

Самый простой способ - аннотировать ваши геттеры и сеттеры.

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

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
    }
}
person Joe Allen    schedule 21.02.2013

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

public class User {
    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    private String password;
}
person Frank Pavageau    schedule 16.03.2018
comment
Это отличное решение, простое, работающее. Спасибо. - person dhqvinh; 23.10.2019
comment
да. Спасибо. По какой-то причине обычные @ JsonProperty в сеттере и @ JsonIgnore в геттере у меня абсолютно не работали. Я не могу понять почему, но это решило проблему. Спасибо. - person Forrest; 19.01.2021
comment
StackOverflow должен выдавать несколько голосов, каждый раз, когда я забываю эту аннотацию, SO возвращает к вашему ответу, спасибо, приятель. - person Neeraj Jain; 19.01.2021

Помимо @JsonIgnore, есть еще пара возможностей:

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

transient - это решение для меня. Благодарность! он встроен в Java и позволяет вам не добавлять еще одну аннотацию, специфичную для фреймворка.

person maxxyme    schedule 13.02.2013
comment
Это работает, если ваш атрибут действительно временный, например, не задействованный ORM .... Я обнаружил, что @JsonIgnore более интересен в моем случае, хотя я был бы привязан к Джексону, но это хороший компромисс - person Joao Pereira; 25.10.2013
comment
Вам не нужно быть привязанным к Джексону, если вы создаете свою собственную аннотацию и аннотируете ее с помощью JsonIgnore и JacksonAnnotationsInside. Таким образом, если вы меняете сериализаторы, вам нужно будет изменить только свою собственную аннотацию. - person DavidA; 20.06.2014

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

public boolean checkPassword(String password){
  return this.password.equals(anyHashingMethod(password));
}
person Albert Waninge    schedule 25.11.2016
comment
Я действительно думаю, что это лучший способ подумать о решении. Имеет смысл сделать вещи, которые вам нужны, приватными и управлять ими с самого объекта. - person arcynum; 17.01.2017

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

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

@JsonIgnore

Это позволяет пропускать переменную сериализатором json.

person Pravin Bansal    schedule 02.11.2018