Contents

Jackson序列化 Map 对象中空值

1. 概述

在这篇快速文章中,我们将研究一个更高级的使用Jackson 的用例——使用包含空值或空键的Map

2. 忽略映射中的空值

Jackson 有一种简单但有用的方法来全局控制 Map 被序列化时 null 值发生的情况:

ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(Include.NON_NULL);

现在通过此映射器序列化的 Map 对象中的任何空值都将被忽略:

@Test
public void givenIgnoringNullValuesInMap_whenWritingMapObjectWithNullValue_thenIgnored() 
  throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();
    mapper.setSerializationInclusion(Include.NON_NULL);
    MyDto dtoObject1 = new MyDto();
    Map<String, MyDto> dtoMap = new HashMap<String, MyDto>();
    dtoMap.put("dtoObject1", dtoObject1);
    dtoMap.put("dtoObject2", null);
    String dtoMapAsString = mapper.writeValueAsString(dtoMap);
    assertThat(dtoMapAsString, containsString("dtoObject1"));
    assertThat(dtoMapAsString, not(containsString("dtoObject2")));
}

3. 使用 Null 键序列化映射

默认情况下,Jackson 不允许使用 null key 对 Map 进行序列化。如果你尝试写出这样的地图,你会得到以下异常:

c.f.j.c.JsonGenerationException: 
  Null key for a Map not allowed in JSON (use a converting NullKeySerializer?)
    at c.f.j.d.s.i.FailingSerializer.serialize(FailingSerializer.java:36)

然而,该库足够灵活,您可以定义自定义的空键序列化程序并覆盖默认行为:

class MyDtoNullKeySerializer extends StdSerializer<Object> {
    public MyDtoNullKeySerializer() {
        this(null);
    }
    public MyDtoNullKeySerializer(Class<Object> t) {
        super(t);
    }
    
    @Override
    public void serialize(Object nullKey, JsonGenerator jsonGenerator, SerializerProvider unused) 
      throws IOException, JsonProcessingException {
        jsonGenerator.writeFieldName("");
    }
}

现在带有 null 键的 Map 可以正常工作——并且 null 键将被写为一个空字符串:

@Test
public void givenAllowingMapObjectWithNullKey_whenWriting_thenCorrect() 
throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();
    mapper.getSerializerProvider().setNullKeySerializer(new MyDtoNullKeySerializer());
    MyDto dtoObject = new MyDto();
    dtoObject.setStringValue("dtoObjectString");
 
    Map<String, MyDto> dtoMap = new HashMap<String, MyDto>();
    dtoMap.put(null, dtoObject);
    String dtoMapAsString = mapper.writeValueAsString(dtoMap);
    assertThat(dtoMapAsString, containsString("\"\""));
    assertThat(dtoMapAsString, containsString("dtoObjectString"));
}

4. 忽略空字段

除了 Maps,Jackson 还提供了很多配置和灵活性来忽略/处理一般的null字段。您可以查看本教程 以确切了解其工作原理。