Como especificar jackson para usar apenas campos - de preferência globalmente


189

O comportamento padrão do jackon parece usar as propriedades (getters e setters) e os campos para serializar e desserializar para json.

Eu gostaria de usar os campos como a fonte canônica de configuração de serialização e, portanto, não quero que o jackson veja as propriedades.

Eu posso fazer isso em uma classe individual com a anotação:

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

Mas não quero colocar isso em todas as aulas ...

É possível configurar isso globalmente? Como adicionar alguns ao Mapeador de Objetos?


1
Tim deu uma boa resposta. Outra possibilidade é que, se você tiver uma classe base comum, poderá colocar anotações de classe nessa; anotações são herdadas por Jackson.
precisa saber é o seguinte

1
Eu acho que eu tentei isso, mas parece que você tem que dizer as subclasses de usar o que as define caso base ...
Michael Wiles

2
Não, a menos que a subclasse substitua a anotação de classe, as anotações dos pais são visíveis como se fossem parte da definição de subclasse (se não, isso seria um bug). Não é necessariamente assim que o JDK lida com as anotações, mas Jackson implementa a herança completa para anotações (mesmo para anotações de método).
precisa saber é o seguinte

Cuidado com a INFER_PROPERTY_MUTATORSbandeira. Força a visibilidade dos levantadores se houver um campo ou getter visível.
Ondra Žižka

Respostas:


157

Você pode configurar ObjectMappers individuais como este:

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

Se você deseja defini-lo globalmente, geralmente acesso um mapeador configurado por meio de uma classe de wrapper.


3
Bom, embora eu ache que você também precise definir o verificador (os métodos Xxx () geralmente criam um novo objeto). Então, algo como 'mapper.setVisibilityChecker (mapper.getVisibilityChecker (). With ...);'
precisa saber é o seguinte

@StaxMan boa chamada em setVisibilityChecker, editei a resposta para refletir.
Kevin Bowersox

42
withGetterVisibilitynão cobre is*métodos, mas existe withIsGetterVisibilitypara eles.
Qerub 12/12/12

13
setVisibilityCheckerestá obsoleto. Use em setVisibilityvez disso.
0x7d7b 06/04/19

1
Isto é exatamente o que eu precisava! Essa configuração me permitiu usar um Mixin para converter facilmente entidades do Hibernate em DTOs. Por padrão, o ObjectMapper serializa tudo e um Mixin precisa especificar quais propriedades ignorar (ou seja, uma subtração em vez de uma interseção).
TastyWheat

150

No Jackson 2.0 e posterior, você pode simplesmente usar:

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;   

...

ObjectMapper mapper = new ObjectMapper();    
mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

para desativar a detecção automática.


1
Oi pessoal, estou usando o jar Jackson 1.9.0. Estou recebendo propriedade json adicional, enquanto serializa o objeto para json string. Preciso obter a string json, que contém apenas variáveis ​​mencionadas com @JsonProperty. Pode me ajudar com isso?
Jrhamza #

7
Você pode começar com anotação classe mencionado em questão OP: @JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)Em seguida, você tem que anotar cada propriedade que deseja incluir com@JsonProperty
Lukk

Obrigado! Antes, encontrei muitos exemplos de código nos quais o JsonMethod foi referenciado em vez do PropertyAccessor. Se você procurar JsonMethod, raramente obtém links para o PropertyAccessor, então ... Qual é a melhor maneira de encontrar nomes de classes de substituição nos artefatos sucessores? Pode ser difícil e desagradável, não?
philburns

38

Especificamente para boolean is*()getters:

Passei muito tempo explicando por que nem abaixo

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

nem isso

  setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE);
  setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE);
  setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

Trabalhei para o meu Boolean Getter / Setter.

A solução é simples:

  @JsonAutoDetect(isGetterVisibility = Visibility.NONE, ...          
  setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE);

UPDATE: inicialização por mola permitida configurá-lo:

jackson:
  visibility.field: any
  visibility.getter: none
  visibility.setter: none
  visibility.is-getter: none

Consulte Propriedades comuns do aplicativo # JACKSON


1
Você poderia elaborar como uma solução simples deve ser aplicada à classe de bean?
Pavel Niedoba

1
Obrigado. Ou seja, Getter salvou o dia para mim.
Grinch #

Esta não é uma resposta para a pergunta e é bastante enganadora.
Ondra Žižka

14

para jackson 1.9.10 eu uso

ObjectMapper mapper = new ObjectMapper();

mapper.setVisibility(JsonMethod.ALL, Visibility.NONE);
mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);

para desativar a dedução automática.


2
Esse é o caminho. Obrigado.
Cuneytykaya

pergunto se há alguma diferença entre fazer isso e desativar o "auto detecta".
Xenoterracide

10

Que tal isso: eu usei com um mixin

objeto não compatível

@Entity
@Getter
@NoArgsConstructor
public class Telemetry {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long pk;
    private String id;
    private String organizationId;
    private String baseType;
    private String name;
    private Double lat;
    private Double lon;
    private Instant updateTimestamp;
}

Mixin:

@JsonAutoDetect(fieldVisibility = ANY, getterVisibility = NONE, setterVisibility = NONE)
public static class TelemetryMixin {}

Uso:

    ObjectMapper om = objectMapper.addMixIn(Telemetry.class, TelemetryMixin.class);
    Telemetry[] telemetries = om.readValue(someJson, Telemetry[].class);

Não há nada que diga que você não pode participar de qualquer número de classes e aplicar o mesmo mixin.

Se você não estiver familiarizado com mixins, eles são conceitualmente simples: A estrutura do mixin é super-imposta sobre a classe alvo (de acordo com Jackson, não tão longe como a JVM está em causa).


3

Se você quiser uma maneira de fazer isso globalmente sem se preocupar com a configuração da sua ObjectMapper, poderá criar sua própria anotação:

@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonAutoDetect(
        getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE,
        setterVisibility = JsonAutoDetect.Visibility.NONE, fieldVisibility = JsonAutoDetect.Visibility.NONE,
        creatorVisibility = JsonAutoDetect.Visibility.NONE
)
public @interface JsonExplicit {
}

Agora você só precisa anotar suas aulas @JsonExplicite pronto!

Lembre-se também de editar a chamada acima @JsonAutoDetectpara garantir que você tenha os valores definidos para o que funciona com o seu programa.

Agradecemos a https://stackoverflow.com/a/13408807 por me ajudar a descobrir sobre@JacksonAnnotationsInside


3

Se você usa o Spring Boot, pode configurar o Jackson globalmente da seguinte maneira:

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@Configuration
public class JacksonObjectMapperConfiguration implements Jackson2ObjectMapperBuilderCustomizer {

    @Override
    public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
        jacksonObjectMapperBuilder.visibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
        jacksonObjectMapperBuilder.visibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
        jacksonObjectMapperBuilder.visibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.ANY);
    }

}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.