Null的Spring Boot JSON序列化

时间:2018-04-05 15:16:25

标签: java spring-boot java-8 jackson

如何在Spring Boot的默认JSON响应中强制将空对象序列化为空字符串?

我希望它显示为:

{
    myProperty: "",
}

但默认情况下出现的是:

{
    myProperty: null,
}

我不希望myProperty被排除在此列表之外,因此我对更改JsonInclude.Include.NON_NULL

不感兴趣

以下是我尝试的内容:

在我的主WebMvcConfigurerAdapter课程中:

@Autowired
private NullAsEmptyStringSerializer nullSerializer;

@Bean
public Jackson2ObjectMapperBuilderCustomizer addCustomSerialization() {
    return jacksonObjectMapperBuilder -> {
        DefaultSerializerProvider serializerProvider = new DefaultSerializerProvider.Impl();
        serializerProvider.setNullValueSerializer(nullSerializer);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setSerializerProvider(serializerProvider);
        jacksonObjectMapperBuilder.configure(objectMapper);
    };

然后我的nullSerializer对象类:

@Component
public class NullAsEmptyStringSerializer extends JsonSerializer<Object> {

    @Override
    public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeString("\"\"");
    }
}

问题是我的自定义类永远不会调用serialize()方法。

1 个答案:

答案 0 :(得分:2)

通过Jackson2ObjectMapperBuilderCustomizer进行此配置的问题在于以下几行:

ObjectMapper objectMapper = new ObjectMapper();
jacksonObjectMapperBuilder.configure(objectMapper);

实际上,这没有任何效果,因为构建器始终使用自己在内部创建的ObjectMapper实例。如果我们检查构建器的源代码:

public <T extends ObjectMapper> T build() {
  ObjectMapper mapper;
  // conditional instantiation of mapper
  configure(mapper);
  return (T) mapper;
}

我们之前的ObjectMapper实例被忽略了。

很遗憾,无法通过SerializerProvider设置Jackson2ObjectMapperBuilder。可能这个功能尚未在API中实现。

但问题至少有两种可能的解决方案。

首先,根据official Spring docs,您始终可以创建自己的标有ObjectMapper的{​​{1}} bean,并根据需要进行完全配置,例如:

@Primary

这将正确启用@Bean @Primary public ObjectMapper objectMapper() { DefaultSerializerProvider serializerProvider = new DefaultSerializerProvider.Impl(); serializerProvider.setNullValueSerializer(nullSerializer); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setSerializerProvider(serializerProvider); return objectMapper; } ,但缺点是Spring nullSerializer实例的自动配置将丢失,这可能不是您一直想要的。

第二个解决方案通过引导ObjectMapper的默认实例并在其上设置所需的属性。这可以通过以一种非常简单的方式实现ObjectMapper接口来实现:

InitializingBean

最后但并非最不重要的是,上面的import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; @Configuration public class ObjectMapperConfig implements InitializingBean { @Autowired private NullAsEmptyStringSerializer nullSerializer; @Autowired private ObjectMapper objectMapper; // will be called by Spring after all the beans are created // and the proper `objectMapper` instance is available here. @Override public void afterPropertiesSet() throws Exception { DefaultSerializerProvider serializerProvider = new DefaultSerializerProvider.Impl(); serializerProvider.setNullValueSerializer(nullSerializer); objectMapper.setSerializerProvider(serializerProvider); } } 存在一个小问题。

NullAsEmptyStringSerializer

将输出jsonGenerator.writeString("\"\""); 。这应该改为

"myProperty":"\"\""