Джексон: як запобігти серіалізації поля


163

У мене є клас сутності з полем пароля:

class User {
    private String password;

    //setter, getter..
}

Я хочу, щоб це поле було пропущено під час серіалізації. Але це все ж має бути в змозі десеріалізувати. Це потрібно, щоб клієнт міг надіслати мені новий пароль, але не зміг прочитати поточний.

Як мені це зробити з Джексоном?


1
Ви не хочете його серіалізувати, але ви хочете мати можливість його десаріалізувати? Це неможливо, я б сказав. Якщо ви не покладете файл cookie у вікно, ви не зможете отримати його з цього поля.
— Олексій Дуфрой

1
@Traroth: але я можу поставити НОВЕ cookie. Я просто шукаю зручну анотацію, але це, безумовно, можна зробити вручну.
— тиждень

8
Швидкий коментар: технічно цілком можливо мати сеттер, який використовується (навіть приватні автоматично виявляються) та просто опустити аксесуар (немає публічного поля чи геттера). Можна також додавати @JsonIgnoreна getter, але @JsonPropertyна setter, і в цьому випадку речі не серіалізуються, але можуть бути десеріалізовані.
— StaxMan

4
Чи не проти прийняти відповідь на це запитання? (Парі вашим іншим кілька років і досі теж неприйнято ... Будь ласка, розгляньте перегляд!) :) Повне розкриття інформації - у мене немає відповідей на жодне з цих питань.
— Баретт

Відповіді:


187

Ви можете позначити його як @JsonIgnore.

З 1.9 ви можете додати @JsonIgnoreдля getter, @JsonPropertyдля сеттера, щоб зробити його деріаріалізованим, але не серіалізувати.


6
@JsonIgnore також запобігає десеріалізації. Для тимчасових - я це перевірю.
— тиждень

98
З 1.9 ви можете додати @JsonIgnoreдля getter, @JsonPropertyдля сеттера, щоб зробити його деріаріалізованим, але не серіалізувати.
— StaxMan

Коментар StaxMan повинен бути відповіддю, чи не так? Чому це все-таки коментар ...! ..?
— Сараванабалаги Рамачандран

схоже, що тимчасовий не працює для мене, я позначив поле "тимчасовим", що я не хочу, щоб воно було серилізовано / дезаріалізоване.
— рохіт

Ця відповідь раніше пропонувала використовувати transient(як у private transient String password;), але перехідні поля з загальнодоступними дітьми ігноруються, якщо MapperFeature.PROPAGATE_TRANSIENT_MARKER не ввімкнено.
— tom

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- <version> .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 для умовного фільтрування полів (за замовчуванням не використовується для десеріалізації; в 2.0 буде доступно, але ви можете використовувати інший погляд на серіалізацію, десеріалізацію)
  • @JsonIgnoreProperties на уроці може бути корисним

10

transientце рішення для мене. Дякую! він є рідним для Java і уникає додавання ще однієї рамкової анотації.


2
Це працює, якщо ваш атрибут справді короткочасний, не задіяний ORM, наприклад .... Знайдений @JsonIgnore є більш цікавим у моєму випадку, хоч би я був заблокований до Джексона, але це вдалий компроміс
— Жоао Перейра

3
Вам не доведеться замикатися на Джексона, якщо ви створюєте свою власну анотацію та її коментують JsonIgnore та JacksonAnnotationsInside. Таким чином, якщо ви змінюєте серіалізатори, вам залишається лише змінити власне анотацію.
— DavidA

4

Слід запитати, чому ви хочете отримати загальнодоступний метод отримання пароля. Зимова сплячка або будь-яка інша рамка 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.