如何使用Jackson对字段进行序列化并忽略NULL、空和不存在的值

5,610 阅读3分钟

学习如何使用Jackson对字段进行序列化并忽略NULL、空和不存在的值。在本教程中,我们将学习不同空值之间的区别以及如何忽略一个特定的值。

1.设置

添加最新版本的Jackson,如果你还没有把它添加到项目中。

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>${jackson.version}</version>
</dependency>

为了演示的目的,我们将使用以下RecordWithNulls类。我们使用Lombok来减少模板代码,如getters, setters, constructors和*toString()*方法。

@lombok.Data
@lombok.AllArgsConstructor
@lombok.NoArgsConstructor
class RecordWithNulls {

  private Long id;
  private String text;
  private LocalDateTime timestamp;
  private Boolean status;
}

2.NULL、空值和缺失值之间的区别

在深入学习代码之前,让我们首先了解空值或缺席值的含义。这样我们就可以更好地决定使用什么选项。

Jackson的枚举JsonInclude.Include ,包含了代表空值或无值的不同数值。

2.1.NULL值

空值是指所有有null 的字段。

2.2.空值

缺少的值包括两种类型。

  • null 值,和
  • 不存在的 "参考类型的值,如OptionalAtomicReference。例如,在调用Optional.get()方法时,没有值存在。Jackson支持来自Java 8的Optionals,以及Guava。

2.3.空值

空值包括null,不存在,以及一些额外的值。这些包括以下类型。

  • null 空值,以及
  • 不存在 "的指代类型的值,如OptionalAtomicReference
  • 长度为0的空字符串。
  • 空的容器,如大小为0的数组/集合。

为了忽略空值和空值,我们使用*@JsonInclude.Include*枚举中存在的一个值。

  • JsonInclude.Include.NON_NULL
  • JsonInclude.Include.NON_ABSENT
  • JsonInclude.Include.NON_EMPTY

3.1.在类的层面上

当在类级别上应用@JsonInclude时,所有具有NULL 值的字段在序列化过程中都会被忽略。

@JsonInclude(JsonInclude.Include.NON_NULL)
class RecordWithNulls {
	...
}

让我们来测试一下。

RecordWithNulls record = new RecordWithNulls(1L, "test", null, null);

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());

String json = mapper.writeValueAsString(record);

上面的代码将产生下面的JSON。

{"id":1,"text":"test"}

3.2.在字段级别

当在字段级应用@JsonInclude时,只有带有NULL 值的注释字段将被忽略。

class RecordWithNulls {
	...
	@JsonInclude(JsonInclude.Include.NON_NULL)
	private LocalDateTime timestamp;
	...
}

生成的JSON中,当时间戳字段为NULL时,将被忽略。状态字段将不会被序列化,因为它没有被注释过。

{"id":1,"text":"test","status":null}

4.全局配置ObjectMapper

如果忽略NULL字段是应用程序的默认行为,那么全局配置是有意义的。实现它的一个方法是在ObjectMapper类中进行配置。

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

现在这个映射器将忽略它序列化的所有类的所有NULL字段。

5.使用自定义过滤器

我们可以通过创建一个自定义过滤器类并重写其equals() 方法来进一步定制空洞的检查。如果*equals()*返回true 值则被排除(即被过滤掉);如果false 值则被包含。

创建一个像下面这样的自定义过滤器。

class StringFilter {
  @Override
  public boolean equals(Object value) {
    //custom logic
    return true;
  }
}

并将其注册为一个字段的自定义过滤器,如下所示。

@JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = StringFilter.class)
private String text;

5.使用自定义序列器

另一种过滤空值的方法是通过重写自定义序列化器类isEmpty() 方法。如果isEmpty()返回true,可以使用@JsonInclude(JsonInclude.Include.NON_EMPTY)将字段从序列化中排除。

class RecordSerializer extends StdSerializer<Record> {
	...
	@Override
  public boolean isEmpty(SerializerProvider provider, Record value) {
  	//write custom logic
    //return super.isEmpty(provider, value);
  }
  ...
}

6.结语

在这个简短的教程中,我们学会了在将POJO序列化为JSON时忽略null、 empty和absence值。我们学会了使用@JsonInclude注解和在ObjectMapper类中设置SerializationInclusion功能。