SpringBoot中返回数据序列化NULL值处理

本文介绍如何在SpringBoot中自定义JSON序列化处理,包括使用Jackson和Fastjson两种方式来美化null值输出,实现更友好的API响应。

 1、使用默认的jackson处理

1、定义json处理方式
public class NullCustomConverter {

    /**
     * json处理器
     */
    public static class MyBeanSerializerModifier extends BeanSerializerModifier {
        private NullArrayJsonSerializer array = new NullArrayJsonSerializer();
        private NullStringJsonSerializer string = new NullStringJsonSerializer();
        private NullNumberJsonSerializer number = new NullNumberJsonSerializer();
        private NullObjectJsonSerializer object = new NullObjectJsonSerializer();

        @Override
        public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
            /*需要进行添加序列化的类型我们可以在这里进行添加和判断*/
            for (int i = 0; i < beanProperties.size(); i++) {
                BeanPropertyWriter writer = beanProperties.get(i);
                /*判断字段的类型,如果是数组或集合则注册nullSerializer*/
                if (isArrayType(writer)) {
                    /*数组*/
                    writer.assignNullSerializer(this.array);
                } else if (isStringType(writer)) {
                    /*字符串*/
                    writer.assignNullSerializer(this.string);
                } else if (isNumberType(writer)) {
                    /*整形*/
                    writer.assignNullSerializer(this.number);
                } else {
                    writer.assignNullSerializer(this.object);
                }
            }
            return beanProperties;
        }
    }

    /**
     * 是否是数组
     */
    private static boolean isArrayType(BeanPropertyWriter writer) {
        Class<?> clazz = writer.getType().getRawClass();
        return clazz.isArray() || Collection.class.isAssignableFrom(clazz);
    }

    /**
     * 是否是String
     */
    private static boolean isStringType(BeanPropertyWriter writer) {
        Class<?> clazz = writer.getType().getRawClass();
        return CharSequence.class.isAssignableFrom(clazz) || Character.class.isAssignableFrom(clazz);
    }

    /**
     * 是否是数值类型
     */
    private static boolean isNumberType(BeanPropertyWriter writer) {
        Class<?> clazz = writer.getType().getRawClass();
        return Number.class.isAssignableFrom(clazz);
    }

    /**
     * 是否是boolean
     */
    private static boolean isBooleanType(BeanPropertyWriter writer) {
        Class<?> clazz = writer.getType().getRawClass();
        return clazz.equals(Boolean.class);
    }

    /**
     * 处理数组集合类型的null值
     */
    private static class NullArrayJsonSerializer extends JsonSerializer<Object> {
        @Override
        public void serialize(Object value, JsonGenerator jsonGenerator,
                              SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeStartArray();
            jsonGenerator.writeEndArray();
        }
    }

    /**
     * 处理字符串类型的null值
     */
    private static class NullStringJsonSerializer extends JsonSerializer<Object> {
        @Override
        public void serialize(Object value, JsonGenerator jsonGenerator,
                              SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeString("");
        }
    }

    /**
     * 处理数值类型的null值
     */
    private static class NullNumberJsonSerializer extends JsonSerializer<Object> {
        @Override
        public void serialize(Object value, JsonGenerator jsonGenerator,
                              SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeNumber(0);
        }
    }

    /**
     * 处理boolean类型的null值
     */
    private static class NullBooleanJsonSerializer extends JsonSerializer<Object> {
        @Override
        public void serialize(Object value, JsonGenerator jsonGenerator,
                              SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeBoolean(false);
        }
    }

    /**
     * 处理实体对象类型的null值
     */
    private static class NullObjectJsonSerializer extends JsonSerializer<Object> {
        @Override
        public void serialize(Object value, JsonGenerator jsonGenerator,
                              SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeStartObject();
            jsonGenerator.writeEndObject();
        }
    }
}

2、配置让我们springboot进行加载

@Configuration
public class JsonConfig {

    @Value("${spring.jackson.date-format}")
    private String dataFormat;

    @Value("${spring.jackson.time-zone}")
    private String timeZone;

    @Bean
    public MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter() {
        final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        ObjectMapper mapper = converter.getObjectMapper();
        /*添加null值设置*/
        mapper.setSerializerFactory(mapper.getSerializerFactory().withSerializerModifier(new NullCustomConverter.MyBeanSerializerModifier()));
        /*日期处理,自定义后一些配置文件里面的信息没有生效,我们手动操作*/
        mapper.setDateFormat(new SimpleDateFormat(dataFormat));
        /*时区处理*/
        mapper.setTimeZone(TimeZone.getTimeZone(timeZone));
        return converter;
    }

}

在测试过程中发现了,我们在配置文件里面配置的属性没有进行加载,所以我们这里手动去操作:

/*日期处理,自定义后一些配置文件里面的信息没有生效,我们手动操作*/
mapper.setDateFormat(new SimpleDateFormat(dataFormat));
/*时区处理*/
mapper.setTimeZone(TimeZone.getTimeZone(timeZone));

2、使用fastjson 

实现我们的WebMvcConfigurer

@Configuration
public class WebContextConfiguration implements WebMvcConfigurer {
   @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        /*添加fastjson*/
        converters.add(fastJsonHttpMessageConverters(converters));
        
    }

    /**
     * 定义fastjson替代jackson,有些地方单独使用了fastjson所以无法使用fastjson做全局配置
     *
     * @return
     */
    private HttpMessageConverter fastJsonHttpMessageConverters(List<HttpMessageConverter<?>> converters) {
        /*排除掉Jackson*/
        for (int i = converters.size() - 1; i >= 0; i--) {
            if (converters.get(i) instanceof MappingJackson2HttpMessageConverter) {
                converters.remove(i);
            }
        }
        FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
        /*自定义fastjson配置*/
        FastJsonConfig config = new FastJsonConfig();
        config.setSerializerFeatures(
                /*是否输出值为null的字段,默认为false,我们将它打开*/
                SerializerFeature.WriteMapNullValue,
                /*将Collection类型字段的字段空值输出为[]*/
                SerializerFeature.WriteNullListAsEmpty,
                /*将字符串类型字段的空值输出为空字符串*/
                SerializerFeature.WriteNullStringAsEmpty,
                /*将数值类型字段的空值输出为0*/
                SerializerFeature.WriteNullNumberAsZero,
                /*自定义日期格式*/
                SerializerFeature.WriteDateUseDateFormat,
                /*禁用循环引用*/
                SerializerFeature.DisableCircularReferenceDetect
        );
        fastJsonHttpMessageConverter.setFastJsonConfig(config);
        /*但是MappingJackson2HttpMessageConverter里面支持的MediaTypes为application/json*/
        List<MediaType> fastMediaTypes = new ArrayList<>();
        fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
        fastJsonHttpMessageConverter.setSupportedMediaTypes(fastMediaTypes);
        return fastJsonHttpMessageConverter;
    }
}

 

<think>我们参考了用户的问题,用户希望了解在Java中如何通过注解或配置跳过null字段序列化。根据引用内容,我们可以结合现有的技术方案来回答。在Spring框架中,常用的JSON序列化库是Jackson。Jackson提供了注解和配置选项来控制在序列化过程中跳过null解决方案:1.使用Jackson的全局配置:在SpringBoot的配置文件(application.properties或application.yml)中设置全局属性,使所有序列化操作都忽略null。2.使用注解:在特定的类或字段上使用Jackson注解,以控制该字段序列化时如果为null则忽略。具体实现:方法一:全局配置在application.properties中添加:```propertiesspring.jackson.default-property-inclusion=non_null```或者在application.yml中添加:```yamlspring:jackson:default-property-inclusion:non_null```这样配置后,整个应用的Jackson序列化都会忽略null字段。方法二:使用注解在需要忽略null的类上使用`@JsonInclude(JsonInclude.Include.NON_NULL)`注解。例如:```java@JsonInclude(JsonInclude.Include.NON_NULL)publicclassMyResponse{privateStringdata;//其他字段...}```这样,这个类的所有字段如果为null,在序列化时将被忽略。如果只想忽略特定字段,可以在字段上使用该注解:```javapublicclassMyResponse{@JsonInclude(JsonInclude.Include.NON_NULL)privateStringdata;//其他字段...}```方法三:使用ObjectMapper配置(适用于非SpringBoot或需要自定义的情况)如果不想使用全局配置或注解,可以在创建ObjectMapper时进行配置:```javaObjectMapperobjectMapper=newObjectMapper();objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);```然后在序列化时使用这个ObjectMapper。注意:全局配置和注解都是针对Jackson的,如果项目中使用的是其他JSON序列化库(如Gson),则需要使用相应的配置方法。根据引用[3]中的内容,我们还可以自定义序列化器来处理特定类型的字段,但针对null处理,上述方法已经足够。总结:用户可以通过配置或注解的方式轻松实现跳过null字段序列化。推荐使用全局配置(如果整个应用都需要)或注解(针对特定类或字段)。相关问题:1.如何在Jackson中自定义日期格式的序列化?2.除了忽略null,Jackson还可以配置哪些序列化特性?3.如何配置Jackson在序列化时忽略空字符串?</think>在 Java 中,可以通过以下方式在对象序列化时跳过 null 字段: ### 1. **使用 Jackson 注解(推荐)** 在类或字段上添加 `@JsonInclude(JsonInclude.Include.NON_NULL)` 注解: ```java import com.fasterxml.jackson.annotation.JsonInclude; @JsonInclude(JsonInclude.Include.NON_NULL) // 类级别:所有 null 字段跳过 public class ResponseDTO { private String name; @JsonInclude(JsonInclude.Include.NON_NULL) // 字段级别:仅跳过该字段 private Integer age; } ``` ### 2. **全局配置(Spring Boot)** 在 `application.properties`/`application.yml` 中配置 Jackson: ```properties # 全局忽略 null spring.jackson.default-property-inclusion=non_null ``` 或 YAML 格式: ```yaml spring: jackson: default-property-inclusion: non_null ``` ### 3. **自定义 ObjectMapper** 手动配置 Jackson 的 `ObjectMapper`: ```java @Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { return new ObjectMapper() .setSerializationInclusion(JsonInclude.Include.NON_NULL); } } ``` ### 4. **Gson 配置(如使用 Gson)** ```java Gson gson = new GsonBuilder() .serializeNulls() // 默认包含 null,设置为 false 可跳过 .create(); ``` ### 效果对比 序列化前: ```json {"name": "Alice", "age": null, "email": null} ``` 序列化后(启用 NON_NULL): ```json {"name": "Alice"} ``` ### 注意事项 - **兼容性**:`@JsonInclude` 是 Jackson 的专属注解,需确保项目使用 Jackson(Spring Boot 默认使用)。 - **局部覆盖**:字段级注解优先级高于类级注解和全局配置。 - **其他选项**: - `NON_EMPTY`:跳过 null 和空集合/字符串 - `NON_ABSENT`:跳过 Optional.empty() 等 > 引用说明:上述方案基于 Jackson 的序列化控制机制,通过注解或配置实现空过滤[^1][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Eeverybody

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值