【问题标题】:Spring Boot JSON Serialization of Nulls空值的 Spring Boot JSON 序列化
【发布时间】:2018-09-15 11:42:07
【问题描述】:

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

我希望它显示为:

{
    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() 方法。

【问题讨论】:

  • {myProperty: } 不是有效的 JSON;你不可能强迫杰克逊产生无效的 JSON。您必须将输出作为字符串进行后处理。考虑创建无效的 JSON 是否是正确的方法。
  • @Bohemian 编辑让您开心。 :-)

标签: java spring-boot java-8 jackson


【解决方案1】:

通过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 实例被忽略了。

很遗憾,无法通过Jackson2ObjectMapperBuilder 设置SerializerProviders。 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("");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-03
    • 1970-01-01
    • 1970-01-01
    • 2018-11-07
    • 2018-04-08
    相关资源
    最近更新 更多