1. Overview 概述

In this quick article, we're going to look at a more advanced use-case of using Jackson – working with Maps that contain null values or null keys.

在这篇里面我们讲学习更进一步的Jackson库的使用方式来处理Maps集合中的空值和键值。

 

 

2. Ignore Nulls Values in a Map 忽略Map集合中的空值

Jackson has a simple but useful way of globally controlling what happens to null values when a Map gets serialized:

Jackson有一个简单高效的方式来全局处理序列化Map集合时的空值情况,代码如下:

ObjectMapper mapper = new ObjectMapper();
// 设置仅包含非空值
mapper.setSerializationInclusion(Include.NON_NULL);

Now any null value in Map object serialized through this mapper is going to be ignored:

一旦如上设置,Map集合的中空值在序列化时就会被忽略掉,示例代码如下:

@Test
public void givenIgnoringNullValuesInMap_whenWritingMapObjectWithNullValue_thenIgnored() 
  throws JsonProcessingException {
    // 设置序列化对象
    ObjectMapper mapper = new ObjectMapper();
    // 仅保留非空值
    mapper.setSerializationInclusion(Include.NON_NULL);
    // 要转为JSON的Java数据对象
    MyDto dtoObject1 = new MyDto();
    // 要序列化的Map集合
    Map<String, MyDto> dtoMap = new HashMap<String, MyDto>();
    dtoMap.put("dtoObject1", dtoObject1);
    dtoMap.put("dtoObject2", null);
    // 调用方法序列化Map为JSON数据
    String dtoMapAsString = mapper.writeValueAsString(dtoMap);
    // 断言判断是不包含空值属性
    assertThat(dtoMapAsString, containsString("dtoObject1"));
    assertThat(dtoMapAsString, not(containsString("dtoObject2")));
}

 

  

3. Serializing a Map With a Null Key 处理Map中的空KEY

By default, Jackson doesn't allow the serialization of a Map with a null key. If you do try to write out such a map, you'll get the following exception:

默认情况下,Jackson不允许序列化存在空值的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)

The library is however flexible enough that you can define a custom, null key serializer and override the default behavior:

不过呢,由于Jackson库有很好的伸缩性可扩展性,因此可以自定义一个空值的序列化器来覆盖掉默认处理空值时抛出异常的行为,示例如下:

// 自定义的序列化空值时行为
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("");
    }
}

Now the Map with the null key will work just fine – and the null key will be written as an empty String:

这样的话,处理具有空KEY的MAP集合就不会抛异常了,可以正常工作。空KEY则会被输出为空字符串,示例代码如下:

@Test
public void givenAllowingMapObjectWithNullKey_whenWriting_thenCorrect() 
throws JsonProcessingException {
    // 序列化对象
    ObjectMapper mapper = new ObjectMapper();
    // 设置空值时的序列化处理
    mapper.getSerializerProvider().setNullKeySerializer(new MyDtoNullKeySerializer());

    // 要处理的数据
    MyDto dtoObject = new MyDto();
    dtoObject.setStringValue("dtoObjectString");
 
    // 空KEY的MAP集合
    Map<String, MyDto> dtoMap = new HashMap<String, MyDto>();
    dtoMap.put(null, dtoObject);

    // 序列化MAP为JSON数据
    String dtoMapAsString = mapper.writeValueAsString(dtoMap);

    // 断言来判断是否成功
    assertThat(dtoMapAsString, containsString("\"\""));
    assertThat(dtoMapAsString, containsString("dtoObjectString"));
}

 

  

4. Ignore Null Fields 忽略空值属性

Besides Maps, Jackson provides a lot of configuration and flexibility for ignoring/working with null fields in general. You can check out this tutorial to see exactly how that works.

除了Map集合外,Jackson库也提供了一系列的可伸缩扩展配置来忽略或处理空值属性,可以点击 这里 来学习下如何做的

 

 

5. Conclusion 最后

Serializing a Map object is common enough that we need a library that's able to handle the nuances of the serialization process well. Jackson provides a few handy customization options to help you shape the output of this serialization process quite well.

序列化Map集合是稀松平常的操作,因此我们需要一个处理库来完成这个过程以及了解这个过程。Jackson库提供了一个便捷的自定义操作来帮助开发人员格式化输出内容。

It also provides a lot of solid ways to work with collections in a more general sense.

同时Jackson库也提供了一堆硬核操作来处理集合

The implementation of all these examples and code snippets can be found in over on GitHub

以上的示例代码实现都可以在 GitHub 上找到,是基于Maven构建的,所以可以轻松克隆到本地运行。大家关注点赞哈