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


Tengo una a Map<String,Foo> foosMap que quiero serializar a través de Jackson . Ahora quiero seguir dos configuraciones en el proceso de serialización:

  1. El mapa puede tener muchos valores nulos y claves nulas y no quiero que los nulos sean serializados.
  2. Para todos aquellos Foos que están siendo serializados, no quiero serializar objetos nulos referenciados dentro de Foo.

¿Cuál es la mejor manera de lograr esto ? Estoy usando frascos jackson-core1.9 y jackson-mapper1.9 en mi proyecto.

Author: Programmer Bruce, 2012-07-12

4 answers

Si es razonable alterar la estructura de datos original Map para ser serializada para representar mejor el valor real deseado para ser serializado, eso es probablemente un enfoque decente, que posiblemente reduciría la cantidad de configuración de Jackson necesaria. Por ejemplo, simplemente elimine las entradas de clave null, si es posible, antes de llamar a Jackson. Dicho esto...


Para suprimir la serialización de entradas Map con valores nulos:

Antes de Jackson 2.9

Usted todavía puede hacer uso de WRITE_NULL_MAP_VALUES, pero tenga en cuenta que se ha movido a SerializationFeature:

mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);

Desde Jackson 2.9

El WRITE_NULL_MAP_VALUES está en desuso, puede usar el equivalente a continuación:

mapper.setDefaultPropertyInclusion(
   JsonInclude.Value.construct(Include.ALWAYS, Include.NON_NULL))

Para suprimir las propiedades de serialización con valores nulos, puede configurar el ObjectMapper directamente, o hacer uso del @JsonInclude anotación:

mapper.setSerializationInclusion(Include.NON_NULL);

O:

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

  Foo(String bar)
  {
    this.bar = bar;
  }
}

Para manejar las claves null Map, es necesaria alguna serialización personalizada, lo mejor que entiendo.

Un enfoque simple para serializar null claves como cadenas vacías (incluyendo ejemplos completos de las dos configuraciones mencionadas anteriormente):

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;

public class JacksonFoo
{
  public static void main(String[] args) throws Exception
  {
    Map<String, Foo> foos = new HashMap<String, Foo>();
    foos.put("foo1", new Foo("foo1"));
    foos.put("foo2", new Foo(null));
    foos.put("foo3", null);
    foos.put(null, new Foo("foo4"));

    // System.out.println(new ObjectMapper().writeValueAsString(foos));
    // Exception: Null key for a Map not allowed in JSON (use a converting NullKeySerializer?)

    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
    mapper.setSerializationInclusion(Include.NON_NULL);
    mapper.getSerializerProvider().setNullKeySerializer(new MyNullKeySerializer());
    System.out.println(mapper.writeValueAsString(foos));
    // output: 
    // {"":{"bar":"foo4"},"foo2":{},"foo1":{"bar":"foo1"}}
  }
}

class MyNullKeySerializer extends JsonSerializer<Object>
{
  @Override
  public void serialize(Object nullKey, JsonGenerator jsonGenerator, SerializerProvider unused) 
      throws IOException, JsonProcessingException
  {
    jsonGenerator.writeFieldName("");
  }
}

class Foo
{
  public String bar;

  Foo(String bar)
  {
    this.bar = bar;
  }
}

Para suprimir la serialización de las entradas Map con las claves null, sería necesario un procesamiento de serialización personalizado adicional.

 94
Author: Programmer Bruce,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-13 08:37:13

Para las versiones de Jackson

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
 18
Author: AllBlackt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-22 20:17:23

La respuesta parece ser un poco vieja, lo que hice fue usar este mapeador para convertir un MAP

      ObjectMapper mapper = new ObjectMapper().configure(SerializationConfig.Feature.WRITE_NULL_MAP_VALUES, false);

Un simple Map:

          Map<String, Object> user = new HashMap<String,Object>();
            user.put( "id",  teklif.getAccount().getId() );
            user.put( "fname", teklif.getAccount().getFname());
            user.put( "lname", teklif.getAccount().getLname());
            user.put( "email", teklif.getAccount().getEmail());
            user.put( "test", null);

Úsalo así por ejemplo:

      String json = mapper.writeValueAsString(user);
 3
Author: azerafati,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-04 07:57:35

Mi solución, espero ayuda
ObjectMapper personalizado y config para spring xml(conveters de mensajes de registro)

public class PyResponseConfigObjectMapper extends ObjectMapper {
public PyResponseConfigObjectMapper() {
    disable(SerializationFeature.WRITE_NULL_MAP_VALUES); //map no_null
    setSerializationInclusion(JsonInclude.Include.NON_NULL); // bean no_null
}

}

 0
Author: oneyoungping,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-17 07:20:08