Usando @JsonIgnore solo durante la serializzazione, ma non la deserializzazione


325

Ho un oggetto utente che viene inviato da e verso il server. Quando invio l'oggetto utente, non voglio inviare la password con hash al client. Quindi, ho aggiunto @JsonIgnorela proprietà password, ma ciò impedisce anche che venga deserializzato nella password, il che rende difficile iscrivere gli utenti quando non hanno una password.

Come posso @JsonIgnoreapplicare solo alla serializzazione e non alla deserializzazione? Sto usando Spring JSONView, quindi non ho un sacco di controllo su ObjectMapper.

Cose che ho provato:

  1. Aggiungi @JsonIgnorealla proprietà
  2. Aggiungi solo @JsonIgnoresul metodo getter

Risposte:


481

Esattamente come farlo dipende dalla versione di Jackson che stai usando. Questo è cambiato intorno alla versione 1.9 , prima di ciò, è possibile farlo aggiungendo @JsonIgnoreal getter.

Che hai provato:

Aggiungi @JsonIgnore solo sul metodo getter

Fare questo e aggiungere anche@JsonProperty un'annotazione specifica per il nome del campo "password" JSON al metodo setter per la password sull'oggetto.

Versioni più recenti di Jackson hanno aggiunto READ_ONLYe WRITE_ONLYargomenti di annotazione per JsonProperty. Quindi potresti anche fare qualcosa del tipo:

@JsonProperty(access = Access.WRITE_ONLY)
private String password;

I documenti sono disponibili qui .


2
gist.github.com/thurloat/2510887 per Jackson JSON ignora solo la deserializzazione
Hadas,

1
AFAIK devi ancora implementare il setter e annotarlo. Voglio solo il getter per la serializzazione. Qual è il transitorio di cui parli? Questa è un'annotazione JPA AFAIK
Matt Broekhuis il

3
Inoltre, assicurati di rimuovere @JsonProperty dal campo stesso, altrimenti sovrascriverà le tue annotazioni getter / setter
Anton Soradoi

15
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
Mikhail Batcer

1
Jackson-annotations 2.5 non ha la funzione successiva. Jackson-annotations 2.6.3 fa
radiantRazor

98

Per fare ciò, tutto ciò di cui abbiamo bisogno sono due annotazioni:

  1. @JsonIgnore
  2. @JsonProperty

Uso @JsonIgnore sul membro della classe e sul suo getter e @JsonPropertysul suo setter. Un'illustrazione di esempio aiuterebbe a fare questo:

class User {

    // More fields here
    @JsonIgnore
    private String password;

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

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

2
è l'unica cosa che ha funzionato per me con Jackson 2.6.4. Ho fatto del mio meglio per utilizzare @JsonProperty (access = Access.WRITE_ONLY) ma non ha funzionato per me.
cirovladimir,

77

Dalla versione 2.6: un modo più intuitivo è usare l' com.fasterxml.jackson.annotation.JsonPropertyannotazione sul campo:

@JsonProperty(access = Access.WRITE_ONLY)
private String myField;

Anche se esiste un getter, il valore del campo è escluso dalla serializzazione.

JavaDoc dice:

/**
 * Access setting that means that the property may only be written (set)
 * for deserialization,
 * but will not be read (get) on serialization, that is, the value of the property
 * is not included in serialization.
 */
WRITE_ONLY

Nel caso ne avessi bisogno al contrario, basta usare Access.READ_ONLY.


1
Non capisco perché ci siano così pochi voti, questo è un modo elegante per risolvere questo problema, funziona come un fascino. Non è necessario annotare getter, setter e field. Solo campo. Grazie.
CROSP,

Questo è disponibile dalla versione 2.6, vedi fastxml.github.io/jackson-annotations/javadoc/2.6/com/…
Daniel Beer,

Probabilmente la migliore risposta per 2.6+ utenti.
David Dossot,

Assicurati di non utilizzare l' importazione org.codehaus.jackson.annotate . La soluzione di @ DanielBeer funziona per Jackson 2.6.3. Questa dovrebbe essere la risposta accettata ora che Jackson è stato aggiornato.
Kent Bull,

13

Nel mio caso, Jackson ha automaticamente (de) serializzare gli oggetti che ritorno da un controller Spring MVC (sto usando @RestController con Spring 4.1.6). Ho dovuto usare com.fasterxml.jackson.annotation.JsonIgnoreinvece di org.codehaus.jackson.annotate.JsonIgnore, altrimenti, semplicemente non ha fatto nulla.


1
questa è una risposta estremamente utile che mi ha davvero aiutato a trovare la fonte del perché @JsonIgnore non è stato onorato da Jackson ... grazie!
Clint Eastwood,

2
"user": {
        "firstName": "Musa",
        "lastName": "Aliyev",
        "email": "klaudi2012@gmail.com",
        "passwordIn": "98989898", (or encoded version in front if we not using https)
        "country": "Azeribaijan",
        "phone": "+994707702747"
    }

@CrossOrigin(methods=RequestMethod.POST)
@RequestMapping("/public/register")
public @ResponseBody MsgKit registerNewUsert(@RequestBody User u){

        root.registerUser(u);

    return new MsgKit("registered");
}  

@Service
@Transactional
public class RootBsn {

    @Autowired UserRepository userRepo;

    public void registerUser(User u) throws Exception{

        u.setPassword(u.getPasswordIn());
        //Generate some salt and  setPassword (encoded -  salt+password)
        User u=userRepo.save(u);

        System.out.println("Registration information saved");
    }

}

    @Entity        
@JsonIgnoreProperties({"recordDate","modificationDate","status","createdBy","modifiedBy","salt","password"})
                    public class User implements Serializable {
                        private static final long serialVersionUID = 1L;

                        @Id
                        @GeneratedValue(strategy=GenerationType.AUTO)
                        private Long id;

                        private String country;

                        @Column(name="CREATED_BY")
                        private String createdBy;

                        private String email;

                        @Column(name="FIRST_NAME")
                        private String firstName;

                        @Column(name="LAST_LOGIN_DATE")
                        private Timestamp lastLoginDate;

                        @Column(name="LAST_NAME")
                        private String lastName;

                        @Column(name="MODIFICATION_DATE")
                        private Timestamp modificationDate;

                        @Column(name="MODIFIED_BY")
                        private String modifiedBy;

                        private String password;

                        @Transient
                        private String passwordIn;

                        private String phone;

                        @Column(name="RECORD_DATE")
                        private Timestamp recordDate;

                        private String salt;

                        private String status;

                        @Column(name="USER_STATUS")
                        private String userStatus;

                        public User() {
                        }
                // getters and setters
                }

4
In futuro potrebbe essere utile fornire anche una breve descrizione di come funziona il codice.
KWILLIAMS,

Tutto a posto !! Cosa stai provando qui? Ottieni più voti? lol
Balaji Boggaram Ramanarayan,

0

Un altro modo semplice per gestire questo è usare l'argomento allowSetters=true nell'annotazione. Ciò consentirà la deserializzazione della password nel dto ma non la serializzerà in un corpo di risposta che utilizza contiene oggetto.

esempio:

@JsonIgnoreProperties(allowSetters = true, value = {"bar"})
class Pojo{
    String foo;
    String bar;
}

Entrambi fooe barsono popolati nell'oggetto, ma solo il foo è scritto in un corpo di risposta.


È stato un mio errore, non mi ero reso conto che avessi già corretto lo snippet. Osservando le tue modifiche, sembra che i miei anni di scrittura in Groovy mi abbiano preso e la mia traduzione in Java è stata un po 'approssimativa. Scusa!
Dhandley,
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.