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?

Michael Wiles
fuente
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
Y otros .
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.

Tim Helmstedt
fuente
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.

lukk
fuente
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

Grigory Kislin
fuente
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.

mfe
fuente
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).

Christian Bongiorno
fuente
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

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

}
Veces
fuente