Ainda não tem acesso? Estude com a gente! Matricule-se
Ainda não tem acesso? Estude com a gente! Matricule-se

Solucionado (ver solução)

Spring e o get das classes, seria um problema?

Boa noite senhores, tudo bem?

Não sei se se seria um problema, mas a primeira vista não me senti confortável com o comportamento do Spring, de que para retornar um json ele leva em cosideração os getters e nãos os atributos. Explicarei melhor abaixo:

Controller:

@RestController
public class TestesSpring{

    @RequestMapping(value="/")
    @ResponseBody
    public RequestTest enviar(RequestTest request){
        return request;
    } 

}

Objeto de RequestTest:

public class RequestTest {

    private long id;

    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }

    public String getQualquerCoisa(){
        return "Qualquer coisa!!";

    }
}

E ao chamar a URL "http://localhost:8080/?id=1" é retornado o seguinte json:

{
    id: 1,
    qualquerCoisa: "Qualquer coisa!!"
}

Eu esperava que somente o id fosse retornado, pois só o id é atributo da classe. Gostaria saber da opinião dos senhores sobre isso, e se teria alguma adaptação pratica para que isso não aconteça?

Desde já agradeço, e me desculpe se a duvida estiver no lugar errado xP

7 respostas

Olá, Allan.

Na verdade, é o comportamento padrão do Jackson, a biblioteca de serialização/desserialização usada pelo Spring MVC.

Para mudar o comportamento padrão, você pode usar a seguinte anotação, logo acima da classe:

 @JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)

Maravilha Alexandre, essa annotation já resolve 99,99% dos casos acredito eu.

Porem se a classe, é um classe de terceiros, ou seja não esta diretamente no projeto eu não consigo colocar essa annotation.

Desculpe ser o chato da vez kkkk, mas teria como faz um configuração global para isso? Tipo tornar esse o comportamento padrão de todas as classes sem ter que anotá-las?

Mas muito obrigado pela informação, ja me ajudou de certa forma.

Atenciosamente,

solução

Olá, Allan.

Lembrei de outra maneira: é usar a anotação @JsonIgnore logo acima do getter que você quer ignorar. Mas é mais específica que a anotação anterior.

É possível definir uma configuração global, criando seu próprio ObjectMapper:

ObjectMapper mapper  = new ObjectMapper();
mapper.setVisibilityChecker(mapper.getSerializationConfig().getDefaultVisibilityChecker()
  .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
  .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
  .withSetterVisibility(JsonAutoDetect.Visibility.NONE)
 .withCreatorVisibility(JsonAutoDetect.Visibility.NONE));

Você teria que definir esse ObjectMapper em um @Bean. O que acho ruim é que perderíamos as configurações padrão do Spring.

Para não modificar classes de terceiros, você pode usar Mixin annotations.

Opa!! Muito Obrigadoo Alexandre, acho que o problema resolvido, só dei um adapatada poruqe na minha versão aqui o método setVisibilityChecker esta deprecated.

Segue o código:

@Bean
    public ObjectMapper objectMapper() {
         ObjectMapper mapper = new ObjectMapper();
         mapper.setVisibility(PropertyAccessor.GETTER, Visibility.NONE);
         mapper.setVisibility(PropertyAccessor.SETTER, Visibility.NONE);
         mapper.setVisibility(PropertyAccessor.CREATOR, Visibility.NONE);
         mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
         return mapper;
    }

Mas Alexandre uma ultima duvida, eu prometo kkk. Você disse que mudar esse comportamento padrão do Spring seria uma má ideia, só não entendi bem o porque? poderia me esclarecer os pontos negativos pra eu por na balança aqui?

Porque com esse comportamento padrão Spring , um programador novo em Spring como eu pode cair de cabeça em um projeto já em andamento e acabar expondo alguma informação sem querer no JSON de saída, já com a alteração esse risco diminui, certo?

Mas já estou muito satisfeito, já consegui progredir bastante aqui no estudo!

Muito Obrigado!

Allan,

Eu digo mais no sentido de que o Spring configura o Jackson para resolver vários pequenos problemas.

Dá uma olhada: https://github.com/spring-projects/spring-framework/blob/master/spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilder.java

Há várias configurações a mais.

Legal seria achar um jeito de obter o ObjectMapper configurado pelo Spring e modificá-lo !

Alexandre boa tarde,

Não encontrei um modo de reutilizar ObjectMapper propriamente dito, porem encontrei um jeito Jackson2ObjectMapperBuilder cria-lo por mim e modificar o seu resultado.

Segue o código:

@Bean
    public ObjectMapper objectMapperBuilder(Jackson2ObjectMapperBuilder builder) {

        return builder
                    .build()
                    .setVisibility(PropertyAccessor.GETTER, Visibility.NONE)
                    .setVisibility(PropertyAccessor.SETTER, Visibility.NONE)
                    .setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
    }

Aparentemente foi um boa solução, muito obrigado Alexandre!

Até a próxima!

Excelente, Allan!

Muito obrigado por compartilhar! Essa solução realmente é ótima!