最近我更新了我的项目从Spring Boot 2.1.0到Spring Boot 2.5.6。从那以后,我看到了JSON序列化的不同之处。
为了区分以下情况(a)任意值, (b)显式null和(c)无值,我使用java.util.Optional
和Jackson的@JsonInclude(NON_NULL)
注释。此外,我使用Spring Data JPA的投影模式定义JSON格式如下:
public interface MyProjection {
@JsonInclude(Include.NON_NULL)
Optional<String> getMyAttribute();
}
这在Spring Boot 2.1.0中运行得很好。
字段值 | 呈现的JSON | Optional.of("something") | { "myAttribute": "something" } |
---|---|
Optional.empty() | { "myAttribute": null } |
null | {} |
经过几次搜索,我找到了感兴趣的测试用例。
下面是jackson项目中可选测试用例的摘录:
public void testConfigAbsentsAsNullsTrue() throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Jdk8Module().configureAbsentsAsNulls(true));
OptionalData data = new OptionalData();
String value = mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL).writeValueAsString(data);
assertEquals("{}", value);
}
public void testConfigAbsentsAsNullsFalse() throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Jdk8Module().configureAbsentsAsNulls(false));
OptionalData data = new OptionalData();
String value = mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL).writeValueAsString(data);
assertEquals("{"myString":null}", value);
}
class OptionalData {
public Optional<String> myString = Optional.empty();
}
可选链接: https://github.com/FasterXML/jackson-datatype-jdk8/blob/master/src/test/java/com/fasterxml/jackson/datatype/jdk8/TestConfigureAbsentsAsNulls.java
还有一个注释configureAbsentsAsNulls。https://github.com/FasterXML/jackson-datatype-jdk8/blob/master/src/main/java/com/fasterxml/jackson/datatype/jdk8/Jdk8Module.java
For compatibility with older versions
* of other "optional" values (like Guava optionals), it can be set to 'true'. The
* default is `false` for backwards compatibility.
public Jdk8Module configureAbsentsAsNulls(boolean state) {
_cfgHandleAbsentAsNull = state;
return this;
}
所以你只需要设置configureAbsentsAsNulls(true)来回滚你之前的状态。
似乎我不能再使用java.util.Optional
为我的目的。Spring开发人员扩展了ProjectingMethodInterceptor
,将null
值转换为所使用的包装器类型的空表示(在我的例子中是Optional.empty()
)。
这也适用于其他包装器类型:
com.google.common.base.Optional
scala.Option
io.vavr.control.Option
我已经使用@JsonSerialize(include = Inclusion.NON_NULL)
来解决这个问题,它起作用了。
有三种方法可以忽略空字段1)。字段级别2)。类级别3)。全局
@JsonInclude (Include.NON_NULL)private String userName;
@JsonInclude(Include.NON_NULL)
public class Book implements Comparable<Book> {
private String title;
private String author;
private int price;
public Book(String title, String author, int price) {
this.title = title;
this.author = author;
this.price = price;
}
}
// let's create a book with author as null
Book book = new Book(null, null, 42);
ObjectMapper mapper = new ObjectMapper();
// configure ObjectMapper to exclude null fields whiel serializing
mapper.setSerializationInclusion(Include.NON_NULL);
String json =mapper.writeValueAsString(cleanCode);
System.out.println(json);