环境:SpringBoot2.7.16
1. 简介
RESTful API已成为前后端交互的标配。而在构建这些API时,我们往往需要根据不同的客户端、用户角色或业务需求,灵活地控制返回的数据结构和内容。Jackson库的@JsonView注解为我们提供了一种优雅且高效的方式来实现这一目标。
@JsonView允许开发者在序列化Java对象为JSON时,定义哪些属性应该被包含在内,哪些应该被排除。这种机制使得我们可以在不修改实体类本身的情况下,改变JSON的输出结构,从而实现了数据的精细控制。
使用@JsonView,我们可以创建多个视图,每个视图代表了一组特定的字段。然后,在控制器的方法上,我们可以通过应用这些视图来指定应该使用哪些字段来序列化返回的实体对象。这种灵活性使得我们能够轻松应对各种复杂的业务需求。
在本文中,通过了解@JsonView,你将能够更好地掌握如何在Spring Boot应用中定制JSON数据的输出,从而提供更加灵活、安全且高效的RESTful API服务。
2. 应用场景
数据暴露级别的控制:
根据用户角色定制数据:
API 版本控制:
数据聚合和拆分:
假设你有一个用户实体(User),包含了一些基本信息(如姓名、年龄)和一些敏感信息(如密码、邮箱、身份证)。当你需要提供一个 API 来获取用户的基本信息时,你可能不希望暴露敏感信息。通过使用 @JsonView,你可以定义两个视图:一个包含基本信息,另一个包含所有信息。然后,在对应的 API 方法上,你可以使用相应的视图来控制输出的数据。
在某些情况下,不同的用户角色可能需要看到不同级别的数据。例如,管理员可能需要看到用户的所有信息,而普通用户只能看到基本信息。通过使用 @JsonView 和 Spring Security,你可以根据用户的角色来动态地决定应该暴露哪些数据。
当你的 API 随时间发展并引入新功能时,可能会有多个版本的 API。在某些情况下,旧版本的 API 可能不需要包含新引入的字段。通过 @JsonView,你可以为每个 API 版本定义一个视图,并在需要时切换到相应的视图。
在某些情况下,你可能需要将多个实体的数据聚合到一个 JSON 响应中,或者将一个大实体的数据拆分成多个小实体。通过使用 @JsonView,你可以更轻松地实现这种数据的聚合和拆分。
3. 实战案例
3.1 视图规则定义
public interface UserView {// 展示基本信息public interface Basic {}// 没有密码public interface WithoutPassword extends Basic {}// 展示所有的信息(包括敏感信息)public interface Full extends Basic {}}
注意:上面的每一个规则继承Basic,你可以根据自己的规则进行相应的继承。
3.2 域对象定义
public class User {@JsonView(UserView.Basic.class)private Long id ;@JsonView(UserView.Basic.class)private String username ;@JsonView(UserView.Full.class)private String password ;@JsonView({UserView.WithoutPassword.class, UserView.Full.class})private String idNo ;// getter, setter}
@JsonView允许一个视图类的数组,但你只能为每个控制器方法指定一个。如果需要激活多个视图,可以使用复合接口。
3.3 Controller接口
public class JsonViewController {public User userWithout() {User user = new User(1L, "pack", "123123", "110101199001014294") ;return user ;}public User userNoPassword() {User user = new User(1L, "pack", "123123", "110101199001014294") ;return user ;}public User user() {User user = new User(1L, "pack", "123123", "110101199001014294") ;return user ;}}
分别对上面3个接口测试结果如下:
基础信息

无密码

所有信息

通过@JsonView非常方便的控制了不同场景下展示的信息。如果没有该注解你会通过什么方式实现?针对不同的场景定义不同的DTO?通过@JsonIgnore注解?
定义不同的DTO太麻烦,使用@JsonIgnore注解没法控制了所有的接口都将会忽略该字段。整体上看还是使用@JsonView更加的灵活。
3.4 编程方式控制
不想使用在Controller接口上使用@JsonView注解方式,你还可以通过编程的方式控制,通过MappingJacksonValue通过该类也能方便的控制json输出。
@GetMapping("/user/program")public MappingJacksonValue program() {User user = new User(1L, "pack", "123123", "110101199001014294") ;MappingJacksonValue value = new MappingJacksonValue(user);value.setSerializationView(UserView.WithoutPassword.class);return value ;}
注意:这里接口的返回值必须是MappingJacksonValue。

3.5 与其它注解结合
修改域对象,添加如下字段
@JsonView(UserView.Basic.class)@JsonIgnoreprivate String email ;
使用@JsonIgnore注解后会不会输出email呢?

email没有输出。你还可以结合@JsonInclude使用实现更加精细化的控制。
总结:@JsonView 提供了一种灵活且强大的方式来控制序列化的 JSON 数据。通过定义视图和将它们应用到属性和控制器方法上,你可以根据需要暴露不同级别的数据,实现 API 的数据定制化。
以上是本篇文章的全部内容,如对你有帮助就请作者吃个棒棒糖🍭。
完毕!!!
推荐文章
面试官:说说@Configuration与@Component有什么区别?
全新升级:SpringBoot Admin可视化监控工具全面解析
SpringBoot整合Flink CDC,实时追踪数据变动,无缝同步至Redis
SpringBoot3虚拟线程 & 反应式(WebFlux) & 传统Tomcat线程池 性能对比
从零开始构建Spring Boot与Dubbo集成:以Nacos为注册中心
Redis结合Caffeine实现二级缓存:提高应用程序性能



