Jackson: jak zapobiec serializacji pola


163

Mam klasę encji z polem hasła:

class User {
    private String password;

    //setter, getter..
}

Chcę, aby to pole zostało pominięte podczas serializacji. Ale nadal powinien być w stanie DEserialize. Jest to potrzebne, aby klient mógł wysłać mi nowe hasło, ale nie może odczytać obecnego.

Jak mam to osiągnąć z Jacksonem?


1
Nie chcesz go serializować, ale chcesz mieć możliwość deserializacji? Powiedziałbym, że to niemożliwe. Jeśli nie umieścisz pliku cookie w pudełku, nie będziesz mógł go odzyskać z tego pudełka.
— Alexis Dufrenoy

1
@Traroth: ale mogę umieścić NOWE ciasteczko. Szukam tylko wygodnej adnotacji, ale z pewnością można to zrobić ręcznie.
— weekens

8
Krótki komentarz: technicznie jest całkowicie możliwe, aby używać setera (nawet prywatne są wykrywane automatycznie) i po prostu pominąć akcesor (brak pola publicznego lub gettera). Możliwe jest również dodanie @JsonIgnoregettera, ale @JsonPropertysettera, w którym to przypadku rzeczy nie są serializowane, ale mogą być deserializowane.
— StaxMan

4
Czy mógłbyś przyjąć odpowiedź na to pytanie? (Kilka innych ma kilka lat i nadal nie zostało zaakceptowanych ... Proszę rozważyć recenzję!) :) Pełne ujawnienie - nie mam odpowiedzi na żadne z tych pytań.
— Barett

Odpowiedzi:


187

Możesz oznaczyć to jako @JsonIgnore.

W wersji 1.9 możesz dodać @JsonIgnoredla getter, @JsonPropertydla setter, aby deserializował, ale nie serializował.


6
@JsonIgnore zapobiega również deserializacji. Na razie - sprawdzę to.
— weekens

98
W wersji 1.9 możesz dodać @JsonIgnoredla getter, @JsonPropertydla setter, aby deserializował, ale nie serializował.
— StaxMan

Komentarz StaxMan powinien być odpowiedzią, prawda? Dlaczego więc nadal jest to komentarz ...! ..?
— Saravanabalagi Ramachandran

przejściowy nie wydaje się działać dla mnie, zaznaczyłem pole „przejściowe”, że nie chcę, aby było ono poddawane serilizacji / deserializacji.
— rohith

Ta odpowiedź wcześniej sugerowała użycie transient(jak w private transient String password;), ale przejściowe pola z publicznymi pobierającymi są ignorowane, chyba że MapperFeature.PROPAGATE_TRANSIENT_MARKER jest włączony.
— tom

96

Ilustrując to, co powiedział StaxMan, działa to dla mnie

private String password;

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

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

12
Której zależności Json używasz? To nie działa z com.fasterxml.jackson
— Alexander Burakevych

3
Dzięki! @JsonIgnorewydaje się, że na boisku nie jest konieczne.
— Ferran Maylinch

com.fasterxml.jackson.annotation.JsonIgnore from jackson-annotations- <wersja> .jar
— mvmn

Próbowałem tego i nie działa dla mnie. Używam v2.8. Jakaś pomoc?
— Maz,

36

Najłatwiejszym sposobem jest dodanie adnotacji do metod pobierających i ustawiających.

Oto oryginalny przykład zmodyfikowany w celu wykluczenia hasła w postaci zwykłego tekstu, ale następnie dodaj adnotację do nowej metody, która po prostu zwraca pole hasła jako zaszyfrowany tekst.

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

Począwszy od Jacksona 2.6 , właściwość może być oznaczona jako tylko do odczytu lub do zapisu. Jest to prostsze niż hakowanie adnotacji w obu akcesoriach i utrzymuje wszystkie informacje w jednym miejscu:

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

To niesamowite rozwiązanie, proste, działające. Dzięki.
— dhqvinh

17

Oprócz tego @JsonIgnoreistnieje kilka innych możliwości:

  • Użyj widoków JSON, aby odfiltrować pola warunkowo (domyślnie nie jest używany do deserializacji; w wersji 2.0 będzie dostępny, ale możesz użyć innego widoku podczas serializacji, deserializacji)
  • @JsonIgnoreProperties na zajęciach może być przydatne

10

transientjest rozwiązaniem dla mnie. dzięki! jest natywny dla języka Java i pozwala uniknąć dodawania kolejnej adnotacji specyficznej dla platformy.


2
To działa, jeśli twój atrybut jest naprawdę przejściowy, na przykład nie dotyczy ORM ... Znaleziony @JsonI Ignoruj, aby był bardziej interesujący w moim przypadku, chociaż byłbym zamknięty w Jacksonie, ale to dobry kompromis
— Joao Pereira

3
Nie musisz ograniczać się do jacksona, jeśli tworzysz własną adnotację i masz ją opatrzoną adnotacjami JsonIgnore i JacksonAnnotationsInside. W ten sposób, jeśli zmienisz serializatory, wystarczy zmienić własną adnotację.
— DavidA

4

Należy zapytać, dlaczego chcesz mieć publiczną metodę pobierania hasła. Hibernate lub jakikolwiek inny framework ORM zrobi z prywatną metodą pobierającą. Aby sprawdzić, czy hasło jest poprawne, możesz użyć

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

Właściwie uważam, że to najlepszy sposób myślenia o rozwiązaniu. Bardziej sensowne jest oznaczanie potrzebnych rzeczy jako prywatne i kontrolowanie ich z poziomu samego obiektu.
— arcynum

2

Jackson ma klasę o nazwie SimpleBeanPropertyFilter, która pomaga filtrować pola podczas serializacji i deserializacji; nie globalnie. Myślę, że tego chciałeś.

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

    //setter, getter..
}

Następnie w swoim kodzie:

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);

Zapobiegnie passwordto serializacji pola. Będziesz także mógł deserializować passwordpola w obecnej postaci. Upewnij się tylko, że na obiekcie ObjectMapper nie zastosowano żadnych filtrów.

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

0

ustaw zmienną jako

@JsonIgnore

Dzięki temu zmienna może zostać pominięta przez serializator json

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.