代码之家  ›  专栏  ›  技术社区  ›  Josh Maag

Spring Boot JSON空序列化

  •  1
  • Josh Maag  · 技术社区  · 7 年前

    如何在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 回复  |  直到 7 年前
        1
  •  3
  •   Antot    7 年前

    此配置的问题通过 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 s到 Jackson2ObjectMapperBuilder 。此功能可能尚未在API中实现。

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

    第一 ,根据 official Spring docs ,您可以随时创建自己的 ObjectMapper 标记为的bean @Primary 并按照您的意愿进行充分配置,例如:

    @Bean
    @Primary
    public ObjectMapper objectMapper() {
      DefaultSerializerProvider serializerProvider = new DefaultSerializerProvider.Impl();
      serializerProvider.setNullValueSerializer(nullSerializer);
      ObjectMapper objectMapper = new ObjectMapper();
      objectMapper.setSerializerProvider(serializerProvider);
      return objectMapper;
    }
    

    这将启用 nullSerializer 正确,但缺点是Spring的 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":"\"\"" 。应将此更改为

    jsonGenerator.writeString("");
    
    推荐文章