Как предотвратить нулевые значения внутри карты и нулевые поля внутри bean от сериализации через Jackson

У меня есть a Map<String,Foo> foosMap, который я хочу сериализовать через Jackson. Теперь я хочу выполнить два параметра в процессе сериализации:

  • Карта может иметь множество нулевых значений и нулевые ключи, и я не хочу, чтобы нули были сериализованы.
  • Для всех тех Foos, которые становятся сериализованными, я не хочу сериализовывать нулевые объекты, на которые ссылаются внутри Foo.

Каков наилучший способ достичь этого? В моем проекте я использую jackson-core1.9 и jackson-mapper1.9.

Ответ 1

Если разумно изменить исходную структуру данных Map, которая будет сериализована, чтобы лучше представлять фактическое значение, которое требуется сериализовать, это, вероятно, достойный подход, который, возможно, уменьшит необходимую конфигурацию Джексона. Например, просто удалите записи null, если это возможно, перед тем, как позвонить в Джексон. Тем не менее...


Чтобы подавить сериализацию записей Map с нулевыми значениями, вы все равно можете использовать WRITE_NULL_MAP_VALUES, но обратите внимание, что он переместился на SerializationFeature:

mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);

Чтобы подавить сериализацию свойств с нулевыми значениями, вы можете настроить ObjectMapper напрямую или использовать @JsonInclude аннотация:

mapper.setSerializationInclusion(Include.NON_NULL);

или

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

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

Чтобы обращаться с нулевыми ключами Map, необходима некоторая пользовательская сериализация, насколько я понимаю.

Простой подход к сериализации null ключей как пустых строк (включая полные примеры двух ранее упомянутых конфигураций):

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

Чтобы подавить сериализацию записей Map с помощью клавиш null, потребуется дополнительная обработка пользовательской сериализации.

Ответ 2

Для версий Jackson < 2.0 используйте эту аннотацию для сериализуемого класса:

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)

Ответ 3

Ответ кажется немного старым. Что я сделал, так это использовать этот преобразователь для преобразования MAP

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

простой 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);

Используйте его, например:

      String json = mapper.writeValueAsString(user);

Ответ 4

мое решение, надеюсь помощь
пользовательский ObjectMapper и config на spring xml (регистрировать конвейеры сообщений)

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

}