Jackson: come prevenire la serializzazione sul campo


163

Ho una classe di entità con un campo password:

class User {
    private String password;

    //setter, getter..
}

Voglio che questo campo venga ignorato durante la serializzazione. Ma dovrebbe essere ancora in grado di serializzare. Questo è necessario, in modo che il client possa inviarmi una nuova password, ma non è in grado di leggere quella corrente.

Come realizzo questo con Jackson?


1
Non vuoi serializzarlo, ma vuoi essere in grado di deserializzarlo? È impossibile, direi. Se non inserisci un cookie in una scatola, non sarai in grado di recuperarlo da questa scatola.
Alexis Dufrenoy,

1
@Traroth: ma posso inserire un NUOVO cookie. Sto solo cercando un'annotazione conveniente, ma questo può sicuramente essere fatto a mano.
settimana

8
Commento rapido: è completamente possibile, tecnicamente, avere un setter che viene utilizzato (anche quelli privati ​​vengono rilevati automaticamente) e omettere semplicemente l'accessor (nessun campo pubblico o getter). È anche possibile aggiungere @JsonIgnoresu getter, ma @JsonPropertysu setter, nel qual caso le cose non sono serializzate, ma possono essere deserializzate.
StaxMan,

4
Ti dispiacerebbe accettare una risposta a questa domanda? (Un paio di altri hanno qualche anno e sono ancora non accettati ... Ti preghiamo di prendere in considerazione la revisione!) :) Divulgazione completa - Non ho risposte a nessuna di queste domande.
Barett,

Risposte:


187

Puoi contrassegnarlo come @JsonIgnore.

Con 1.9, puoi aggiungere @JsonIgnoreper getter, @JsonPropertyper setter, per renderlo deserializzato ma non serializzato.


6
@JsonIgnore impedisce anche la deserializzazione. Per i transitori - lo controllerò.
settimana

98
Con 1.9, puoi aggiungere @JsonIgnoreper getter, @JsonPropertyper setter, per renderlo deserializzato ma non serializzato.
StaxMan

Il commento di StaxMan dovrebbe essere la risposta, no? Perché è ancora un commento allora ...! ..?
Saravanabalagi Ramachandran,

il transitorio non sembra funzionare per me, ho contrassegnato il campo "transitorio" che non desidero che sia serializzato / deserializzato.
Rohith,

Questa risposta in precedenza suggeriva di utilizzare transient(come in private transient String password;) ma i campi transitori con getter pubblici vengono ignorati a meno che MapperFeature.PROPAGATE_TRANSIENT_MARKER non sia abilitato.
Tom,

96

Illustrando ciò che StaxMan ha affermato, questo funziona per me

private String password;

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

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

12
Quale dipendenza Json usi? Questo non funziona con com.fasterxml.jackson
Alexander Burakevych il

3
Grazie! @JsonIgnorenon è necessario sul campo, a quanto pare.
Ferran Maylinch,

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

Ho provato questo e non funziona per me. Uso v2.8. Qualsiasi aiuto?
Maz

36

Il modo più semplice è annotare i tuoi getter e setter.

Ecco l'esempio originale modificato per escludere la password di testo normale, ma poi annotare un nuovo metodo che restituisce il campo password come testo crittografato.

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

A partire da Jackson 2.6 , una proprietà può essere contrassegnata come sola lettura o sola scrittura. È più semplice che hackerare le annotazioni su entrambi gli accessori e conserva tutte le informazioni in un unico posto:

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

Questa è una soluzione fantastica, semplice, funzionante. Grazie.
dhqvinh,

17

A parte @JsonIgnore, ci sono un paio di altre possibilità:

  • Usa le viste JSON per filtrare i campi in modo condizionale (per impostazione predefinita, non utilizzato per la deserializzazione; in 2.0 sarà disponibile ma è possibile utilizzare una vista diversa su serializzazione, deserializzazione)
  • @JsonIgnoreProperties in classe può essere utile

10

transientè la soluzione per me. Grazie! è nativo di Java ed evita di aggiungere un'altra annotazione specifica per il framework.


2
Funziona se il tuo attributo è davvero transitorio, non coinvolto ORM, per esempio .... Ho trovato @JsonIgnore più interessante nel mio caso, anche se sarei bloccato a Jackson, ma è un buon compromesso
Joao Pereira,

3
Non devi essere bloccato su Jackson se crei la tua annotazione e la fai annotare da JsonIgnore e JacksonAnnotationsInside. In questo modo, se cambi i serializzatori, devi solo cambiare la tua annotazione.
David,

4

Ci si dovrebbe chiedere perché si desidera un metodo getter pubblico per la password. Hibernate, o qualsiasi altro framework ORM, funzionerà con un metodo getter privato. Per verificare se la password è corretta, è possibile utilizzare

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

In realtà penso che questo sia il modo migliore per pensare alla soluzione. Ha più senso rendere private le cose di cui hai bisogno e controllarle dall'oggetto stesso.
arcynum

2

Jackson ha una classe chiamata SimpleBeanPropertyFilter che aiuta a filtrare i campi durante la serializzazione e la deserializzazione; non a livello globale. Penso che sia quello che volevi.

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

    //setter, getter..
}

Quindi nel tuo codice:

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

Ciò impedirà che il passwordcampo venga serializzato. Inoltre sarai in grado di deserializzare i passwordcampi così come sono. Assicurati solo che non vengano applicati filtri sull'oggetto ObjectMapper.

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

0

imposta variabile come

@JsonIgnore

Ciò consente alla variabile di essere ignorata dal serializzatore json

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.