¿Cómo decirle a Jackson que ignore un campo durante la serialización si su valor es nulo?

687

¿Cómo se puede configurar Jackson para ignorar un valor de campo durante la serialización si el valor de ese campo es nulo?

Por ejemplo:

public class SomeClass {
   // what jackson annotation causes jackson to skip over this value if it is null but will 
   // serialize it otherwise 
   private String someValue; 
}
ams
fuente

Respuestas:

1102

Para suprimir las propiedades de serialización con valores nulos usando Jackson> 2.0, puede configurar ObjectMapperdirectamente o hacer uso de la @JsonIncludeanotación:

mapper.setSerializationInclusion(Include.NON_NULL);

o:

@JsonInclude(Include.NON_NULL)
class Foo
{
  String bar;
}

Alternativamente, puede usarlo @JsonIncludeen un captador para que el atributo se muestre si el valor no es nulo.

Un ejemplo más completo está disponible en mi respuesta a Cómo evitar que los valores nulos dentro de un Mapa y los campos nulos dentro de un bean se serialicen a través de Jackson .

Programador Bruce
fuente
81
para mi proyecto, esto funcionó: @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL); de alguna manera tu anotación no estaba disponible.
Emmanuel Touzery
13
La API cambió un poco con la versión 2.0.
Programador Bruce
10
@ProgrammerBruce -1 cambia tu respuesta en consecuencia ya que estás al tanto del cambio.
Martin Asenov
19
Sí, acabo de confirmar que la @JsonIncludenotación no funciona, pero esto funciona de @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) maravilla : (Estoy usando Jackson 1.9.12 con Spring 3.2.2.)
gstroup
17
@MartinAsenov: la respuesta muestra la API más reciente; se cambió de la @JsonSerializesintaxis a @JsonInclude. La sintaxis anterior está en desuso.
Logan Pickup
128

Con Jackson> 1.9.11 y <2.x use la @JsonSerializeanotación para hacer eso:

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)

WTK
fuente
10
Hoy en día (Jackson 2.x) este enfoque está en desuso.
rustyx
39
@JsonInclude (JsonInclude.Include.NON_NULL)
ZiglioUK
3
@JsonSerialize(using = FooSerializer.class, include = JsonSerialize.Inclusion.NON_NULL)no funciona los valores anulables se serializan.
herau
1
Está en desuso, pero si necesita mantener cosas viejas, ¡esta respuesta está totalmente bien! así que gracias @WTK :)
DominikAngerer
Como nota al margen, Jackson 1.9.12 es estándar en WebSphere 8.5, espero que esta información le ahorre a alguien más tiempo que me tomó resolver esto :-)
bakoyaro
122

Solo para ampliar las otras respuestas: si necesita controlar la omisión de valores nulos por campo, anote el campo en cuestión (o, alternativamente, anote el 'captador' del campo).

ejemplo: aquí solo fieldOnese omitirá de json si es nulo. fieldTwosiempre se incluirá independientemente de si es nulo.

public class Foo {

    @JsonInclude(JsonInclude.Include.NON_NULL) 
    private String fieldOne;

    private String fieldTwo;
}

Para omitir todos los valores nulos en la clase por defecto, anote la clase. Las anotaciones por campo / captador todavía se pueden usar para anular este valor predeterminado si es necesario.

ejemplo: aquí fieldOney fieldTwose omitirá de json si son nulos, respectivamente, porque este es el valor predeterminado establecido por la anotación de clase. fieldThreesin embargo, anulará el valor predeterminado y siempre se incluirá, debido a la anotación en el campo.

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Foo {

    private String fieldOne;

    private String fieldTwo;

    @JsonInclude(JsonInclude.Include.ALWAYS)
    private String fieldThree;
}

ACTUALIZAR

Lo anterior es para Jackson 2 . Para versiones anteriores de Jackson necesitas usar:

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) 

en vez de

@JsonInclude(JsonInclude.Include.NON_NULL)

Si esta actualización es útil, vota la respuesta de ZiglioUK a continuación, ¡señaló la nueva anotación Jackson 2 mucho antes de que actualizara mi respuesta para usarla!

davnicwil
fuente
¿No debería anularse SIEMPRE la anotación en el campo?
Abhinav Vishak
@AbhinavVishak tienes razón, ¡gracias! Fue un error tipográfico copiar y pegar cuando actualicé la respuesta para usar Jackson 2. Editado.
davnicwil
@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) está en desuso
Yar
1
@Yar sí, eso está en desuso en Jackson 2.x. Yo he dicho que es necesario usar que sólo en versiones anteriores de Jackson, donde no sólo se no desuso, es la única opción.
davnicwil
60

En Jackson 2.x, use:

@JsonInclude(JsonInclude.Include.NON_NULL)
ZiglioUK
fuente
es esto para ser colocado en el campo.
enms.
1
@ams, esta anotación debería envolver una clase
Edgard Leal
¿Podría incluir también el nombre completo? Jackson tiene múltiples anotaciones con el mismo nombre y un paquete diferente, por lo que es ambiguo.
Vince
¿Estás diciendo que hay varias anotaciones @JsonInclude en Jackson? No tenía ni idea. ¿Cuál debería ser el nombre completo entonces? no dude en editar la respuesta
ZiglioUK
La confusión con los nombres probablemente se deba a que Jackson 1.xy 2.x utilizan diferentes paquetes de Java para todo, para evitar conflictos con el cargador de clases (versiones de clase incompatibles con wrt). Dado que esta respuesta es para 2.x, el paquete para anotaciones sería com.fasterxml.jackson.annotation: Jackson 1.x teníaorg.codehaus.jackson.annoation
StaxMan el
39

Puede usar la siguiente configuración del mapeador:

mapper.getSerializationConfig().setSerializationInclusion(Inclusion.NON_NULL);

Desde 2.5 puedes usar:

mapper.setSerializationInclusion(Include.NON_NULL);
Eren Yilmaz
fuente
3
Como esto está en desuso en 1.9, use mapper.getSerializationConfig (). WithSerializationInclusion (JsonSerialize.Inclusion.NON_NULL);
Asa
77
..o directamente: mapper.setSerializationInclusion (NON_NULL);
Asa
@ruslan: Probablemente porque la documentación de getSerializationConfig() dice:Note that since instances are immutable, you can NOT change settings by accessing an instance and calling methods: this will simply create new instance of config object.
Zero3
Para uso 2.5.4mapper.setSerializationInclusion(Include.NON_NULL);
Arturo Volpe
12

en mi caso

@JsonInclude(Include.NON_EMPTY)

Lo hizo funcionar.

Alfthan
fuente
2
NON_EMPTY es sutilmente diferente de NON_NULL: ignorará los valores nulos, eso es cierto, pero también ignorará los valores considerados vacíos, que pueden no ser el comportamiento deseado. Ver los Jackson Javadocs para más información
davnicwil
Me gusta esta respuesta porque devolver Opcional de cosas que son realmente opcionales es una buena idea, y con solo NON_NULL obtendría algo como { }nulo, que transfiere sin sentido un idioma de Java al consumidor. lo mismo con AtomicReference: al consumidor no le importa cómo el desarrollador eligió hacer cumplir la seguridad de los hilos en la representación interna de la respuesta.
Lucas Ross
8
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonInclude(JsonInclude.Include.NON_EMPTY)

Deberia trabajar.

Include.NON_EMPTYindica que la propiedad se serializa si su valor no es nulo y no está vacío. Include.NON_NULLindica que la propiedad se serializa si su valor no es nulo.

Neha Gangwar
fuente
2
JsonInclude.Include.NON_EMPTY- es suficiente ya que cubre el caso NOT_NULL
Ilya Buziuk
5

Si desea agregar esta regla a todos los modelos en Jackson 2.6+ use:

mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
Ilia Kurtov
fuente
5

Esto funcionará en Spring boot 2.0.3+ y Jackson 2.0+

import com.fasterxml.jackson.annotation.JsonInclude;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class ApiDTO
{
    // your class variable and 
    // methods
}
Deva
fuente
1
Eso mismo @JsonInclude(JsonInclude.Include.NON_NULL)funcionó para mí en Spring boot 2.1.2 y las anotaciones de Jackson 2.9.0
manasouza
@manasouza Sí, han mantenido la coherencia en todas las actualizaciones.
Deva
3

Para Jackson 2.5 use:

@JsonInclude(content=Include.NON_NULL)
Bilal BBB
fuente
2

Esto me ha estado preocupando durante bastante tiempo y finalmente encontré el problema. El problema se debió a una importación incorrecta. Anteriormente había estado usando

com.fasterxml.jackson.databind.annotation.JsonSerialize

Que había quedado en desuso. Simplemente reemplace la importación por

import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;

y úsalo como

@JsonSerialize(include=Inclusion.NON_NULL)
usuario3443646
fuente
2

Configuración global si usa Spring

@Configuration
public class JsonConfigurations {

    @Bean
    public Jackson2ObjectMapperBuilder objectMapperBuilder() {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.serializationInclusion(JsonInclude.Include.NON_NULL);
        builder.serializationInclusion(JsonInclude.Include.NON_EMPTY);
        builder.failOnUnknownProperties(false);
        return builder;
    }

}
Xelian
fuente
La configuración de serializationInclusion no agrega uno sobre otro. public Jackson2ObjectMapperBuilder serializationInclusion(JsonInclude.Include serializationInclusion) { this.serializationInclusion = serializationInclusion; return this; }; Uno debería usar el radio de enumeración de inclusión mayor. por ejemplo, NON_ABSENT incluye NON_NULL y NON_EMPTY incluye ambos. Por lo tanto, solo debería ser builder.serializationInclusion(JsonInclude.Include.NON_EMPTY); JacksonInclude doc
Olgun Kaya
2

Si está intentando serializar una lista de objetos y uno de ellos es nulo, terminará incluyendo el elemento nulo en el JSON incluso con

mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

resultará en:

[{myObject},null]

para obtener esto:

[{myObject}]

uno puede hacer algo como:

mapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
        @Override
        public void serialize(Object obj, JsonGenerator jsonGen, SerializerProvider unused)
                throws IOException
        {
            //IGNORES NULL VALUES!
        }
    });

SUGERENCIA: si está utilizando DropWizard, puede recuperar el ObjectMapperque Jersey está utilizandoenvironment.getObjectMapper()

usuario3474985
fuente
1

Tenemos muchas respuestas a esta pregunta. Esta respuesta puede ser útil en algunos escenarios. Si desea ignorar los valores nulos, puede usar NOT_NULL en el nivel de clase. como a continuación

@JsonInclude(Include.NON_NULL)
class Foo
{
  String bar;
}

Algunas veces es posible que deba ignorar los valores vacíos, como haber inicializado el arrayList, pero no hay elementos en esa lista. En ese momento, use la anotación NOT_EMPTY para ignorar esos campos de valores vacíos

@JsonInclude(Include.NON_EMPTY)
class Foo
{
  String bar;
}

fuente
0

Jackson 2.x + uso

mapper.getSerializationConfig().withSerializationInclusion(JsonInclude.Include.NON_NULL);
mekdev
fuente
.withSerializationInclusion(JsonInclude.Include.NON_NULL)en lugar correcto?
herau
Gracias por señalarlo, no
esperaré para
@ruslan: Probablemente porque la documentación de getSerializationConfig()dice:Note that since instances are immutable, you can NOT change settings by accessing an instance and calling methods: this will simply create new instance of config object.
Zero3
0

Además, debe cambiar su enfoque al usar Map myVariable como se describe en la documentación para eliminar los valores nulos:

From documentation:
com.fasterxml.jackson.annotation.JsonInclude

@JacksonAnnotation
@Target(value={ANNOTATION_TYPE, FIELD, METHOD, PARAMETER, TYPE})
@Retention(value=RUNTIME)
Annotation used to indicate when value of the annotated property (when used for a field, method or constructor parameter), or all properties of the annotated class, is to be serialized. Without annotation property values are always included, but by using this annotation one can specify simple exclusion rules to reduce amount of properties to write out.

*Note that the main inclusion criteria (one annotated with value) is checked on Java object level, for the annotated type, and NOT on JSON output -- so even with Include.NON_NULL it is possible that JSON null values are output, if object reference in question is not `null`. An example is java.util.concurrent.atomic.AtomicReference instance constructed to reference null value: such a value would be serialized as JSON null, and not filtered out.

To base inclusion on value of contained value(s), you will typically also need to specify content() annotation; for example, specifying only value as Include.NON_EMPTY for a {link java.util.Map} would exclude Maps with no values, but would include Maps with `null` values. To exclude Map with only `null` value, you would use both annotations like so:
public class Bean {
   @JsonInclude(value=Include.NON_EMPTY, content=Include.NON_NULL)
   public Map<String,String> entries;
}

Similarly you could Maps that only contain "empty" elements, or "non-default" values (see Include.NON_EMPTY and Include.NON_DEFAULT for more details).
In addition to `Map`s, `content` concept is also supported for referential types (like java.util.concurrent.atomic.AtomicReference). Note that `content` is NOT currently (as of Jackson 2.9) supported for arrays or java.util.Collections, but supported may be added in future versions.
Since:
2.0
atom88
fuente
0

Caso uno

@JsonInclude(JsonInclude.Include.NON_NULL)
private String someString;

Caso dos

@JsonInclude(JsonInclude.Include.NON_EMPTY)
private String someString;

Si someStringes nulo, se ignorará en ambos casos. SisomeString es "" solo se ignorará en el caso dos.

Lo mismo para List = nulloList.size() = 0

Nguyen Minh Hien
fuente