Spring MVC 过滤 JSON 数据的完整指南
在 Spring MVC 开发中,处理 JSON 数据是常见的需求,有时我们需要对返回的 JSON 数据进行过滤,以隐藏敏感信息或控制输出字段,本文将详细介绍在 Spring MVC 中如何实现 JSON 数据过滤的多种方法。
使用 Jackson 注解进行字段过滤
Jackson 提供了多个注解可以帮助我们控制 JSON 序列化过程,从而实现字段过滤。
1 @JsonIgnore
@JsonIgnore 注解可以标记某个属性在序列化时被忽略。
public class User {
private String username;
private String password;
@JsonIgnore
public String getPassword() {
return password;
}
// getters and setters
}
2 @JsonIgnoreProperties
类级别注解,可以指定一组需要忽略的属性。
@JsonIgnoreProperties({"password", "internalId"})
public class User {
private String username;
private String password;
private String internalId;
// getters and setters
}
3 @JsonInclude
控制哪些属性应该被包含在序列化结果中。
@JsonInclude(JsonInclude.Include.NON_NULL)
public class User {
private String username;
private String password; // 如果为null则不会出现在JSON中
// getters and setters
}
使用自定义序列化器
对于更复杂的过滤逻辑,可以实现自定义的 JsonSerializer。
public class CustomUserSerializer extends JsonSerializer<User> {
@Override
public void serialize(User user, JsonGenerator gen, SerializerProvider provider)
throws IOException {
gen.writeStartObject();
gen.writeStringField("username", user.getUsername());
// 不包含password字段
gen.writeEndObject();
}
}
然后在模型类上使用 @JsonSerialize 注解:
@JsonSerialize(using = CustomUserSerializer.class)
public class User {
// fields and methods
}
使用 Spring MVC 的 @ResponseBodyAdvice
ResponseBodyAdvice 允许在响应体写入前进行拦截和修改。
@ControllerAdvice
public class JsonFilterAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType,
Class<? extends HttpMessageConverter<?>> converterType) {
return converterType.equals MappingJackson2HttpMessageConverter.class);
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType,
MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response) {
if (body instanceof User) {
User user = (User) body;
// 创建一个新对象只包含需要的字段
Map<String, Object> filteredUser = new HashMap<>();
filteredUser.put("username", user.getUsername());
return filteredUser;
}
return body;
}
}
使用 DTO 模式
创建专门的数据传输对象(DTO)来控制输出字段。
public class UserDTO {
private String username;
// 构造方法、getters和setters
}
public class User {
private String username;
private String password;
// 转换为DTO的方法
public UserDTO toDTO() {
UserDTO dto = new UserDTO();
dto.setUsername(this.username);
return dto;
}
}
然后在控制器中返回 DTO 而不是实体类:
@GetMapping("/users/{id}")
public UserDTO getUser(@PathVariable Long id) {
User user = userService.findById(id);
return user.toDTO();
}
动态过滤(基于请求参数)
有时需要根据请求参数动态过滤 JSON 数据。
@GetMapping("/users/{id}")
public ResponseEntity<?> getUser(
@PathVariable Long id,
@RequestParam(required = false) Set<String> fields) {
User user = userService.findById(id);
ObjectMapper mapper = new ObjectMapper();
if (fields != null && !fields.isEmpty()) {
// 只包含请求的字段
mapper.setFilterProvider(new SimpleFilterProvider()
.addFilter("userFilter", SimpleBeanPropertyFilter.filterOutAllExcept(fields)));
mapper.addMixIn(User.class, UserFilterMixIn.class);
}
return ResponseEntity.ok(mapper.convertValue(user, User.class));
}
// 混合类用于应用过滤器
@JsonIgnoreProperties(ignoreUnknown = true)
abstract class UserFilterMixIn {
}
配置全局 Jackson 设置
在 Spring 配置类中可以设置全局的 Jackson 行为。
@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
// 全局忽略未知属性
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 全局设置null值不序列化
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
return mapper;
}
}
Spring MVC 提供了多种方式来过滤 JSON 数据输出,从简单的注解到复杂的自定义序列化器和拦截器,选择哪种方法取决于具体需求:
- 对于简单的字段忽略,使用 Jackson 注解最方便
- 对于复杂的过滤逻辑,自定义序列化器或
ResponseBodyAdvice更灵活 - 对于严格的 API 控制,DTO 模式是最安全的选择
- 对于需要动态过滤的场景,可以结合请求参数和过滤器实现
合理使用这些技术可以确保 API 只返回客户端需要的数据,提高安全性和性能。



还没有评论,来说两句吧...