👉 这是一个或许对你有用的社群
🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料:
《项目实战(视频)》:从书中学,往事上“练”
《互联网高频面试题》:面朝简历学习,春暖花开
《架构 x 系统设计》:摧枯拉朽,掌控面试高频场景题
《精进 Java 学习指南》:系统学习,互联网主流技术栈
《必读 Java 源码专栏》:知其然,知其所以然

👉这是一个或许对你有用的开源项目
国产Star破10w的开源项目,前端包括管理后台、微信小程序,后端支持单体、微服务架构
RBAC权限、数据权限、SaaS多租户、商城、支付、工作流、大屏报表、ERP、CRM、AI大模型、IoT物联网等功能:
多模块:https://gitee.com/zhijiantianya/ruoyi-vue-pro
微服务:https://gitee.com/zhijiantianya/yudao-cloud
视频教程:https://doc.iocoder.cn
【国内首批】支持 JDK17/21+SpringBoot3、JDK8/11+Spring Boot2双版本

前后端分离的项目中,使用Json字符串 来完成前后端之间的通信。在默认情况下,只要前端发起请求,就会返回对象的所有 字段。但有的时候,后端不能把所有字段全部返回。
一方面,是因为有些字段前端不需要,返回过多的数据会占用网络带宽;
另一方面是出于安全性 考虑,比如,不可以将密码返回给前端,否则,网站攻击者可以用REST工具直接获取密码。
而JsonView的作用,就是用来控制C层返回哪些字段 的。
@JsonView 它是 Jackson 库中的一个强大注解。通过定义不同的视图类(通常为接口或类),并在实体类的字段上使用 @JsonView 注解标记该字段在哪个视图中可见,同时在控制器方法中通过 @JsonView 注解指定返回的视图,就可以灵活控制返回的字段内容,实现了根据不同场景动态选择序列化字段的目的,大大提高了代码的简洁性和可维护性。
JsonView的效果
通过以下几个实例的对比,来展示JsonView的效果。
以下的代码,我们通过一个小Demo来演示:
在这个小小的教务系统中,有三种实体——教师、学生、班级 ,
为了清晰的展示实体关系,提供简单的E-R图:
由图可知: 班级和教师是多对一 的关系, 学生和班级是多对一 的关系 因此,如果查询学生,班级会包含在学生的字段中,教师会包含在班级的字段中。 这是典型的“对象套对象套对象”的例子。
下面实体的代码供参考(可略过):
1、不使用JsonView
在不使用JsonView的情况下,使用REST工具直接取出一个学生,返回了学生的所有字段,也包含关联查询 得到的对象:
{
"id":1,
"name":"学生1",
"sno":"123456",
"klass":{
"id":1,
"teacher":{
"id":1,
"name":"张三",
"sex":false,
"username":"zhangsan",
"email":"123@123.com"
},
"name":"班级1"
}
}
因此,很容易得到结论一:
不使用JsonView时,返回所有字段,包括外键关联对象的所有字段
2、在实体的字段上使用JsonView
在原来的基础上,对姓名和学号字段分别使用JsonView,同时,定义对应的接口:
在C层控制器中加入NameJsowView: (注意:此时只有姓名 ,并没有加入学号和班级)
返回结果如下:
{
"name":"学生1"
}
由于我们在C层只使用了姓名的字段,除了姓名,其他字段均不返回。
因此可以得出结论二:
对于已经定义JsowView的对象,C层只返回注解中的JsonView接口里面包含的字段,其他字段一概不返回。
3、在实体的关联对象中使用JsonView
前一节的基础上,把C层的注解由 @JsonView(Student.NameJsonView.class) 改为**@JsonView(Student.KlassJsonView.class)** 来返回学生对象关联的班级。
这次的返回结果比较有意思,只返回了空的Klass,里面一个字段也没有:
{
"klass":
{
}
}
所以,结论三:通过外键关联的对象,使用JsonView只会返回关联空对象本身,而不返回关联对象的任何字段。
4、在关联对象的字段中使用JsonView
为了解决结论三的问题,我们需要像上文一样,在学生关联的班级 实体中也启用JsonView。
然后新建一个接口,分别继承班级 字段以及班级实体中的姓名 、教师 等其他字段:
public interface GetByIdJsonView extends Student.KlassJsonView, Klass.NameJsonView, Klass.TeacherJsonView {}
把这个新接口写到C层方法的注解上:
@GetMapping("{id}")
@JsonView(GetByIdJsonView.class)
public Student getById(@PathVariable Long id) {
return this.studentService.findById(id);
}
再次运行,查看返回结果:
{
"klass":
{
"teacher":{ },
"name":"班级1"
}
}
符合预期,因此,结论四:
如果想返回关联对象中的字段,只需要继承这个实体中,相关字段的JsonView接口即可。
细心的你可以发现,Teacher中依然没有字段,如果也想返回Teacher的字段,只需要在接口中继续继承即可。
基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://github.com/YunaiV/ruoyi-vue-pro
视频教程:https://doc.iocoder.cn/video/
JsonView的使用方法
接下来说具体如何在Spring的项目中应用JsonView。
1、在实体类中定义接口
需要记住接口名称
// 定义了一个接口,用于JsonView控制返回字段
public interface SnoJsonView {}
2、在实体中的字段中加入注解
找到一个字段,加入**@JsonView(XXXJsonView.class)** ,名称与刚才写的接口名称相同。
@JsonView(SnoJsonView.class)
private String sno;
3、继承接口
实际的项目中,不可能只返回一个字段,如果返回多个字段,那就在C层再定一个接口,继承所以要返回字段的接口即可。 原则上,每个控制器方法,都必须有唯一的JsonView接口,接口名与方法名相同,不能混用。
定义一个与C层方法名相同的接口,继承业务逻辑中需要返回的所有字段:
public interface GetByIdJsonView extends Student.KlassJsonView, Student.NameJsonView, Student.SnoJsonView {}
4、在C层方法上加入注解
最后一步,就是把刚才的接口,加到要控制字段的C层方法上:
@GetMapping("{id}")
@JsonView(GetByIdJsonView.class)
public Student getById(@PathVariable Long id) {
return this.studentService.findById(id);
}
到此,就可以实现用JsonView控制返回字段了。 这种做法的优点在于: 实体层中,接口名 和字段名 一致,到C层引用时,就可以根据名称知道这个接口控制哪个字段; 控制器中,接口名 与方法名 一致,通过接口名可以知道是这个方法返回哪些字段。
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://github.com/YunaiV/yudao-cloud
视频教程:https://doc.iocoder.cn/video/
总结
前后端分离的项目中,使用Json字符串 来完成前后端之间的通信,但有的时候,后端不能把所有字段全部返回,因此可以使用JsonView,来控制C层返回哪些字段 。
如果不使用JsonView,默认返回所有字段 ,包括外键关联对象的所有信息; 如果使用JsonView,只返回接口中声明 的所有字段,如果出现关联对象,只返回关联对象本身,而不返回其中的字段。 JsonView接口可以通过继承 ,来实现返回不同字段的组合。
欢迎加入我的知识星球,全面提升技术能力。
👉 加入方式,“长按”或“扫描”下方二维码噢:

星球的内容包括:项目实战、面试招聘、源码解析、学习路线。





文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
335



被折叠的 条评论
为什么被折叠?



