问题描述
使用ObjectMapper
做一些实验时,偶然发现了这种行为。请参阅下面的junit5测试用例,并在注释中为我打印出什么内容。
class TestIt {
private ObjectMapper om = new ObjectMapper();
private TestClass testClass = new TestClass();
@Getter @Setter
public class TestClass {
private final String value = LocalDate.Now().toString();
private String valueLeftNull;
}
@Test
void defaultMapping() throws JsonProcessingException {
System.out.println(om.writeValueAsstring(testClass));
// {"value":"2020-11-02","valueLeftNull":null}
}
@Test
void nonNull() throws JsonProcessingException {
om.setSerializationInclusion(Include.NON_NULL);
System.out.println(om.writeValueAsstring(testClass));
// {"value":"2020-11-02"}
}
@Test
void both() throws JsonProcessingException {
System.out.println(om.writeValueAsstring(testClass));
om.setSerializationInclusion(Include.NON_NULL);
System.out.println(om.writeValueAsstring(testClass));
System.out.println(om.writeValueAsstring(new TestClass()));
// {"value":"2020-11-02","valueLeftNull":null}
// {"value":"2020-11-02","valueLeftNull":null}
}
}
最后一个both()
是我想知道的。 ObjectMapper
在第一次序列化后忽略包含指令是正常功能吗?
解决方法
默认情况下,Jackson
为每个POJO
类创建BeanSerializer实例。它是在需要时按需创建的,并缓存。因此,其配置取决于ObjectMapper
的当前状态,如果更改ObjectMapper
,则需要清除缓存:
((DefaultSerializerProvider) om.getSerializerProvider()).flushCachedSerializers();
强制ObjectMapper
创建BeanSerializer
的新实例。
看看BeanSerializerFactory的文档:
...
最后,由于所有缓存均由序列化程序提供程序处理 (不是工厂)并且没有可配置性,该工厂是 无状态的。这意味着可以使用全局单例实例。
可用于确定此序列化器数量的方法 provider当前正在缓存(如果已缓存:默认) 实现的确)确切的数量取决于哪种序列化器 被缓存默认实现会缓存所有序列化程序,包括 渴望建造的(为了获得最佳访问速度)
最好的解决方案可能是创建ObjectMapper
的两个实例:
class TestIt {
private JsonMapper nonNullMapper = JsonMapper.builder()
.serializationInclusion(JsonInclude.Include.NON_NULL)
.build();
private JsonMapper defaultMapper = JsonMapper.builder().build();
private TestClass testClass = new TestClass();
@Getter
@Setter
public static class TestClass {
private final String value = LocalDate.now().toString();
private String valueLeftNull;
}
void defaultMapping() throws JsonProcessingException {
System.out.println(defaultMapper.writeValueAsString(testClass));
}
void nonNull() throws JsonProcessingException {
System.out.println(nonNullMapper.writeValueAsString(testClass));
}
void both() throws JsonProcessingException {
System.out.println(defaultMapper.writeValueAsString(testClass));
System.out.println(nonNullMapper.writeValueAsString(testClass));
System.out.println(nonNullMapper.writeValueAsString(new TestClass()));
}
}