一、針對特定接口null的處理:
方法一:使用 @JsonInclude 注解
1.1 類級別:在接口返回的 ?DTO 類或字段? 上添加 @JsonInclude 注解,強制忽略 null 值:
類級別:所有字段為 null 時不返回
@JsonInclude(JsonInclude.Include.NON_NULL)
public class MyResponseDTO {private String field1;
1.2 字段級別:在具體字段上,僅該字段為 null 時不返回
// 字段級別:僅該字段為 null 時不返回
@JsonInclude(JsonInclude.Include.NON_NULL)
private String field2;
1.3 方法級別: 在方法級別使用 @JsonInclude
如果不想在 DTO 類上全局標注 @JsonInclude
,可以直接在 Controller 方法的返回類型上通過 @JsonSerialize
注解臨時指定序列化行為。
@GetMapping("/user")
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) // 舊版 Jackson 注解
public MyResponse getUser() {MyResponse response = new MyResponse();response.setName("Alice"); // age 為 null,不返回return response;
}
方法二:動態構建響應對象
在 Controller 方法中手動過濾 null 值,使用 Map 或 JSONObject 動態構建響應體:
@GetMapping("/api")
public Map<String, Object> getData() {MyResponseDTO dto = service.getData();Map<String, Object> result = new HashMap<>();if (dto.getField1() != null) {result.put("field1", dto.getField1());}return result;
}
適用于簡單場景,但需手動維護字段映射?。
方法三:自定義序列化邏輯(針對復雜場景)
通過繼承 JsonSerializer 實現特定字段的 null 處理邏輯,并在 DTO 中指定序列化器:
public class NullSerializer extends JsonSerializer<Object> {@Overridepublic void serialize(Object value, JsonGenerator gen, SerializerProvider provider) {// 忽略 null 字段if (value == null) {return;}gen.writeObject(value);}
}// 在 DTO 字段上指定序列化器
public class MyResponseDTO {@JsonSerialize(using = NullSerializer.class)private String field1;
}
適用于需要精細化控制序列化邏輯的場景?。
方法四:自定義 ObjectMapper
并局部使用
通過注入 ObjectMapper
實例,在特定接口中手動序列化數據,跳過 null
值。
@Autowired
private ObjectMapper objectMapper;@GetMapping("/user")
public String getUser(HttpServletResponse response) throws JsonProcessingException {MyResponse data = new MyResponse();data.setName("Alice"); // age 為 null// 臨時配置 ObjectMapper 忽略 nullobjectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);String json = objectMapper.writeValueAsString(data);// 恢復全局配置(可選)objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);response.setContentType(MediaType.APPLICATION_JSON_VALUE);return json;
}
注意:此方法需手動處理響應,適用于需要完全控制序列化邏輯的場景,但需謹慎管理 ObjectMapper
的線程安全性。
方法五:使用 ResponseBodyAdvice
全局攔截并處理
通過實現 ResponseBodyAdvice
接口,對特定接口或全局返回值進行統一處理。
-
定義切面類
@RestControllerAdvice public class NullIgnoreAdvice implements ResponseBodyAdvice<Object> {@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {// 僅處理特定接口(根據注解、包路徑等條件判斷)return returnType.getExecutable().getName().equals("getUser");}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType mediaType, Class selectedConverterType,ServerHttpRequest request, ServerHttpResponse response) {if (body instanceof MyResponse) {// 手動移除 null 值(需根據數據結構處理)((MyResponse) body).setAge(null); // 示例}return body;} }
-
結合
ObjectMapper
動態過濾
在beforeBodyWrite
中重新序列化數據:ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); return mapper.convertValue(body, returnType.getParameterType());
二、針對所有接口null 的處理:
2.1 :全局配置(影響所有接口)
若需所有接口忽略null
值,可在application.properties
中配置:
spring.jackson.default-property-inclusion=non_null
2.2 Springboot 整合 fastjson:
在springboot 啟動類中定義該方法即可
@Beanpublic HttpMessageConverters fastJsonHttpMessageConverters() {FastJsonHttpMessageConverter4 fastConverter = new FastJsonHttpMessageConverter4();FastJsonConfig fastJsonConfig = new FastJsonConfig();fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat, SerializerFeature.IgnoreNonFieldGetter,SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty);fastConverter.setFastJsonConfig(fastJsonConfig);List supportedMediaTypes = new ArrayList();supportedMediaTypes.add(new MediaType("text", "json", Charset.forName("utf8")));supportedMediaTypes.add(new MediaType("application", "json", Charset.forName("utf8")));fastConverter.setSupportedMediaTypes(supportedMediaTypes);HttpMessageConverter<?> converter = fastConverter;return new HttpMessageConverters(converter);}
2.3 Springboot 整合 jackson:
@Configuration
public class JacksonConfig {@Bean@Primary@ConditionalOnMissingBean(ObjectMapper.class)public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {ObjectMapper objectMapper = builder.createXmlMapper(false).build();objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {@Overridepublic void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {jsonGenerator.writeString("");}});return objectMapper;}
}
三、總結:
- 針對新項目,推薦使用全局序列化處理,統一返回值。
- 針對老項目,推薦使用特定接口的處理,避免影響了其他接口的穩定。