web-dev-qa-db-fra.com

Jackson: comment empêcher la sérialisation sur le terrain

J'ai une classe d'entité avec un champ de mot de passe:

class User {
    private String password;

    //setter, getter..
}

Je souhaite que ce champ soit ignoré lors de la sérialisation. Mais il devrait toujours être capable de se désérialiser. Cela est nécessaire pour que le client puisse m'envoyer un nouveau mot de passe mais ne puisse pas lire le mot de passe actuel.

Comment puis-je accomplir cela avec Jackson?

134
weekens

Vous pouvez le marquer comme @JsonIgnore.

Avec 1.9, vous pouvez ajouter @JsonIgnore pour getter, @JsonProperty pour setter, pour le désérialiser mais pas le sérialiser. 

157
Biju Kunjummen

Illustrant ce que StaxMan a déclaré, cela fonctionne pour moi

private String password;

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

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

Le moyen le plus simple est d’annoter vos accesseurs. 

Voici l'exemple original modifié pour exclure le mot de passe en texte brut, puis annotez une nouvelle méthode qui renvoie simplement le champ de mot de passe sous forme de texte crypté.

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
    }
}
33
Joe Allen

En plus de @JsonIgnore, il existe deux autres possibilités:

  • Utilisez Vues JSON pour filtrer les champs de manière conditionnelle (par défaut, non utilisé pour la désérialisation; la version 2.0 sera disponible, mais vous pouvez utiliser différentes vues pour la sérialisation, la désérialisation).
  • @JsonIgnoreProperties sur la classe peut être utile
16
StaxMan

À partir de Jackson 2.6 , une propriété peut être marquée comme étant en lecture ou en écriture seule. C'est plus simple que de pirater les annotations sur les deux accesseurs et de garder toutes les informations au même endroit:

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

transient est la solution pour moi. Merci! il est natif de Java et vous évite d'ajouter une autre annotation spécifique au framework.

7
maxxyme

On devrait se demander pourquoi vous voulez une méthode getter publique pour le mot de passe. Hibernate, ou tout autre framework ORM, utilisera une méthode getter privée. Pour vérifier si le mot de passe est correct, vous pouvez utiliser

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

Jackson a une classe nommée SimpleBeanPropertyFilter qui aide à filtrer les champs lors de la sérialisation et de la désérialisation; pas globalement. Je pense que c'est ce que tu voulais.

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

    //setter, getter..
}

Puis dans votre code:

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

Cela empêchera le champ password d'être sérialisé. Vous pourrez aussi désérialiser les champs password tels quels. Assurez-vous simplement qu'aucun filtre n'est appliqué à l'objet ObjectMapper.

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

définir la variable comme 

@JsonIgnore

Cela permet aux variables d'être ignorées par le sérialiseur json

0
Pravin