空值的 Spring Boot JSON 序列化

Posted

技术标签:

【中文标题】空值的 Spring Boot JSON 序列化【英文标题】:Spring Boot JSON Serialization of Nulls 【发布时间】: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 编辑让您开心。 :-) 【参考方案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("");

【讨论】:

以上是关于空值的 Spring Boot JSON 序列化的主要内容,如果未能解决你的问题,请参考以下文章

Newtonsoft.Json高级用法 1.忽略某些属性 2.默认值的处理 3.空值的处理 4.支持非公共成员 5.日期处理 6.自定义序列化的

使用 Spring boot 解析具有无效键值的 JSON 对象

Spring Boot POST 请求返回 Null 值的端点

Spring Boot中的JSON技术

我怎样才能坚持protobuf网可为空值的数组

Spring Boot REST 服务:JSON 反序列化不起作用