Jackson: como impedir a serialização de campo

163

Eu tenho uma classe de entidade com um campo de senha:

class User {
    private String password;

    //setter, getter..
}

Quero que este campo seja ignorado durante a serialização. Mas ainda deve ser capaz de desserializar. Isso é necessário para que o cliente possa me enviar uma nova senha, mas não consiga ler a atual.

Como faço isso com Jackson?

weekens
fonte
1
Você não deseja serializá-lo, mas deseja desserializá-lo? Isso é impossível, eu diria. Se você não colocar um cookie em uma caixa, não poderá recuperá-lo dessa caixa.
Alexis Dufrenoy
1
@Traroth: mas eu posso colocar um novo cookie. Estou apenas procurando uma anotação conveniente, mas isso certamente pode ser feito manualmente.
weekens 02/02
8
Comentário rápido: tecnicamente, é completamente possível ter um setter usado (mesmo os privados são detectados automaticamente) e apenas omitir o acessador (nenhum campo público ou getter). Também é possível adicionar @JsonIgnoreno getter, mas @JsonPropertyno setter, caso em que as coisas não são serializadas, mas podem ser desserializadas.
StaxMan
4
Você se importaria de aceitar uma resposta para esta pergunta? (Alguns de seus outros têm alguns anos e ainda não são aceitos ... Por favor, considere a revisão!) :) Divulgação completa - Não tenho respostas para nenhuma dessas perguntas.
Barett

Respostas:

187

Você pode marcá-lo como @JsonIgnore.

Com 1.9, você pode adicionar @JsonIgnorepara getter, @JsonPropertypara setter, para desserializar, mas não serializar.

Biju Kunjummen
fonte
6
O @JsonIgnore também impede a desserialização. Para transitório - eu vou dar uma olhada.
weekens 02/02
98
Com 1.9, você pode adicionar @JsonIgnorepara getter, @JsonPropertypara setter, para desserializar, mas não serializar.
StaxMan
O comentário de StaxMan deve ser a resposta, não é? Por que ainda é um comentário então ...! ..?
Saravanabalagi Ramachandran
transitório não parece funcionar para mim, marquei o campo "transitório" que não quero que seja serilizado / desserializado.
Rohith
Esta resposta sugerida anteriormente usando transient(como em private transient String password;), mas os campos transitórios com getters públicos são ignorados, a menos que o MapperFeature.PROPAGATE_TRANSIENT_MARKER esteja ativado.
tom
96

Ilustrando o que o StaxMan afirmou, isso funciona para mim

private String password;

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

@JsonProperty
public void setPassword(String password) {
    this.password = password;
}
Gary
fonte
12
Qual dependência Json você usa? Isso não funciona com com.fasterxml.jackson
Alexander Burakevych
3
Obrigado! @JsonIgnorenão é necessário em campo, ao que parece.
Ferran Maylinch 8/08/14
com.fasterxml.jackson.annotation.JsonIgnore de jackson-annotations- <version> .jar
mvmn
Eu tentei isso e não está funcionando para mim. Eu uso a v2.8. Qualquer ajuda?
Maz
36

A maneira mais fácil é anotar seus getters e setters.

Aqui está o exemplo original modificado para excluir a senha de texto sem formatação, mas anote um novo método que apenas retorna o campo da senha como texto criptografado.

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
    }
}
Joe Allen
fonte
21

A partir do Jackson 2.6 , uma propriedade pode ser marcada como somente leitura ou gravação. É mais simples do que invadir as anotações nos dois acessadores e mantém todas as informações em um só lugar:

public class User {
    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    private String password;
}
Frank Pavageau
fonte
Esta é uma solução incrível, simples e funcional. Obrigado.
dhqvinh
17

Além de @JsonIgnore, existem algumas outras possibilidades:

  • Usar exibições JSON para filtrar os campos condicionalmente (por padrão, não usado para desserialização; no 2.0 estará disponível, mas você pode usar uma visualização diferente na serialização, desserialização)
  • @JsonIgnoreProperties na aula pode ser útil
StaxMan
fonte
10

transienté a solução para mim. obrigado! é nativo para Java e evita que você adicione outra anotação específica da estrutura.

maxxyme
fonte
2
Isso funciona se o seu atributo é realmente transitória, não ORM envolvido, por exemplo .... @JsonIgnore encontrado para ser mais interessante, no meu caso, embora eu seria bloqueado para Jackson, mas é uma boa troca
Joao Pereira
3
Você não precisa estar bloqueado para jackson se criar sua própria anotação e anotá-la por JsonIgnore e JacksonAnnotationsInside. Dessa forma, se você alterar serializadores, precisará alterar apenas sua própria anotação.
Davida
4

Deve-se perguntar por que você deseja um método público getter para a senha. O Hibernate, ou qualquer outra estrutura ORM, funcionará com um método getter privado. Para verificar se a senha está correta, você pode usar

public boolean checkPassword(String password){
  return this.password.equals(anyHashingMethod(password));
}
Albert Waninge
fonte
Na verdade, acho que essa é a melhor maneira de pensar sobre a solução. Faz mais sentido tornar privadas as coisas de que você precisa e controlá-las a partir do próprio objeto.
arcynum
2

Jackson tem uma classe chamada SimpleBeanPropertyFilter que ajuda a filtrar campos durante a serialização e desserialização; não globalmente. Eu acho que é isso que você queria.

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

    //setter, getter..
}

Então no seu código:

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

Isso impedirá que o passwordcampo seja serializado. Além disso, você poderá desserializar os passwordcampos como estão. Apenas verifique se não há filtros aplicados ao objeto ObjectMapper.

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

definir variável como

@JsonIgnore

Isso permite que a variável seja ignorada pelo json serializer

Pravin
fonte