Cómo especificar jackson para usar solo campos, preferiblemente globalmente


192

El comportamiento de jackon predeterminado parece utilizar tanto propiedades (getters y setters) como campos para serializar y deserializar a json.

Me gustaría usar los campos como la fuente canónica de la configuración de serialización y, por lo tanto, no quiero que Jackson vea las propiedades en absoluto.

Puedo hacer esto en una clase individual con la anotación:

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

Pero no quiero tener que poner esto en cada clase ...

¿Es posible configurar esto globalmente? ¿Te gusta agregar algunos al Object Mapper?


1
Tim dio una buena respuesta. Otra posibilidad es que si tiene una clase base común, puede poner anotaciones de clase a esa; Las anotaciones son heredadas por Jackson.
StaxMan

1
Creo que lo intenté, pero parece que tienes que decirle a las subclases que usen lo que define el caso base ...
Michael Wiles

2
No, a menos que la subclase anule la anotación de clase, las anotaciones de los padres son visibles como si fueran parte de la definición de subclase (de lo contrario, esto sería un error). Así no es necesariamente cómo JDK trata con las anotaciones, pero Jackson implementa la herencia completa para las anotaciones (incluso para las anotaciones de método).
StaxMan

Cuidado con la INFER_PROPERTY_MUTATORSbandera. Obliga a la visibilidad de los colocadores si hay un captador o campo visible.
Ondra Žižka

Respuestas:


157

Puede configurar ObjectMappers individuales de esta manera:

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

Si desea establecerlo globalmente, generalmente accedo a un asignador configurado a través de una clase de contenedor.


3
Bien, aunque creo que es posible que también deba configurar el verificador (con los métodos Xxx () generalmente se crea un nuevo objeto). Entonces, algo como 'mapper.setVisibilityChecker (mapper.getVisibilityChecker (). With ...);'
StaxMan

@StaxMan buena llamada en setVisibilityChecker, edité la respuesta para reflejar.
Kevin Bowersox

42
withGetterVisibilityno cubre is*métodos, pero hay withIsGetterVisibilitypara ellos.
qerub

13
setVisibilityCheckeres obsoleto. Usar en su setVisibilitylugar.
0x7d7b

1
¡Esto es justo lo que necesitaba! Esta configuración me permitió usar un Mixin para convertir fácilmente las entidades de Hibernate en DTO. Por defecto, ObjectMapper serializa todo y un Mixin tendría que especificar qué propiedades ignorar (es decir, una resta en lugar de una intersección).
TastyWheat

150

En Jackson 2.0 y versiones posteriores, simplemente puede 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 desactivar la autodetección.


1
Hola chicos, estoy usando Jackson 1.9.0 jar. Estoy obteniendo propiedad json adicional, mientras serializo el objeto en la cadena json. Necesito obtener la cadena json, que contiene solo las variables mencionadas con @JsonProperty. Puedes por favor ayudarme en esto ?
jrhamza

77
Puede comenzar con la anotación de clase mencionada en la pregunta OP: a @JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)continuación, debe anotar cada propiedad que desea incluir@JsonProperty
lukk

¡Gracias! Antes, he encontrado muchos ejemplos de código donde se hizo referencia a JsonMethod en lugar de PropertyAccessor. Si busca JsonMethod, rara vez obtiene enlaces a PropertyAccessor, entonces ... ¿Cuál es la mejor manera de encontrar nombres de clase de reemplazo en artefactos sucesores? Puede ser duro y desagradable, ¿no?
philburns

38

Específicamente para boolean is*()captadores:

He dedicado mucho tiempo a por qué ni a continuación

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

ni esto

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

trabajé para mi Boolean Getter / Setter.

La solución es simple:

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

ACTUALIZACIÓN: spring-boot permitió configurarlo:

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

Ver Propiedades de aplicación comunes # JACKSON


1
¿Podría explicar cómo se debe aplicar una solución simple a la clase de bean?
Pavel Niedoba

1
Gracias. Eso es: Me salvó el día para mí.
grinch

Esta no es una respuesta a la pregunta y es bastante engañosa.
Ondra Žižka

14

para jackson 1.9.10 yo uso

ObjectMapper mapper = new ObjectMapper();

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

a la vuelta de autodedection.


2
Ese es el camino. Gracias.
cuneytykaya

me pregunto si hay alguna diferencia entre hacer esto y deshabilitar la "detección automática".
xenoterracide

10

¿Qué tal esto? Lo usé con un mixin

objeto no conforme

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

No hay nada que diga que no se puede predecir cualquier cantidad de clases y aplicar el mismo mixin.

Si no está familiarizado con mixins, son conceptualmente simple: La estructura del mixin se impuso súper en la clase de objetivo (de acuerdo con Jackson, no en lo que se refiere a la JVM).


3

Si desea una manera de hacer esto globalmente sin preocuparse por la configuración de su ObjectMapper, puede crear su propia anotación:

@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 {
}

¡Ahora solo tienes que anotar tus clases @JsonExplicity listo!

También asegúrese de editar la llamada anterior para @JsonAutoDetectasegurarse de tener los valores establecidos para lo que funciona con su programa.

Gracias a https://stackoverflow.com/a/13408807 por ayudarme a conocer@JacksonAnnotationsInside


3

Si usa Spring Boot, puede configurar Jackson globalmente de la siguiente manera:

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

}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.