@JsonView + 单一 DTO:如何实现多场景 JSON 字段动态渲染

news2025/4/19 18:34:52

@JsonView + 单一 DTO:如何实现多场景 JSON 字段动态渲染

  • @JsonView + 单一 DTO:如何实现多场景 JSON 字段动态渲染
    • 1、@JsonView 注解产生的背景
    • 2、为了满足不同场景下返回对应的属性的做法有哪些?
      • 2.1 最快速的实现则是针对不同场景新建不同的 DTO 对象
      • 2.2 使用 @JsonView 注解实现不同DTO对象的返回
        • 2.2.1 定义同一个 DTO 对象
        • 2.2.2 区分不同的响应视图
        • 2.2.3 Controller 层的调用
        • 2.2.4 简要信息 视图 DTO
        • 2.2.5 详情信息 视图 DTO
      • 2.3 问题已解决(引入原理实现篇)
    • 3、Debug调试篇
      • 3.1 SpringMvc 切入点 对应的核心代码片段
      • 3.2 字段属性序列化核心逻辑
      • 3.3 多种 DTO 视图 Demo 验证
        • 3.3.1 ObjectMapper 配置视图 View
        • 3.3.2 ObjectWriter 配置视图 View
      • 3.4 小结
    • 4、扩展点
      • 4.1 ResponseBodyAdvice接口
      • 4.2 RequestBodyAdvice接口

@JsonView + 单一 DTO:如何实现多场景 JSON 字段动态渲染

1、@JsonView 注解产生的背景

@JsonView 是 Jackson 库提供的一个注解,用于控制 Java 对象序列化为 JSON 时的字段可见性。通过定义不同的“视图”(View),可以灵活地决定哪些字段在特定场景下被序列化,从而避免为不同接口编写多个相似的 DTO 类。

2、为了满足不同场景下返回对应的属性的做法有哪些?

2.1 最快速的实现则是针对不同场景新建不同的 DTO 对象

在这里插入图片描述

细心的童鞋可以发现:虽然是不同的 DTO,但是存在共同的属性,而且比如后面再来一个需求,这个接口仅返回基本信息的字段(外加一个手机号字段),那么我们是不是还需要创建一个新的 DTO 对象呢?如果针对每一个接口返回都定义一个 DTO 对象的话,对于后端代码的维护也是相当的冗余操作,鉴于这种需求,有没有一种对应后端的 其他 解决方案呢?答案是有的。即就是(@JsonView注解)。

2.2 使用 @JsonView 注解实现不同DTO对象的返回

2.2.1 定义同一个 DTO 对象
/**
 * @Description 用户DTO
 * @Author Mr.Gao
 * @Date 2025/4/16 23:43
 */
@Getter
@Setter
public class User {
    /**
     * 用户姓名
     */
    @JsonView(SimpleInfoView.class)
    private String username;
    /**
     * 用户年龄
     */
    @JsonView(SimpleInfoView.class)
    private Integer age;
    /**
     * 用户性别
     */
    @JsonView(SimpleInfoView.class)
    private String sex;

    /**
     * =================以下信息为用户敏感信息不能给用户返回================
     */

    /**
     * 手机号码
     */
    @JsonView(SensitiveInfoView.class)
    private String mobileNo;
    /**
     * 登录密码
     */
    @JsonView(SensitiveInfoView.class)
    private String loginPwd;
    /**
     * 支付密码
     */
    @JsonView(SensitiveInfoView.class)
    private String payPwd;
}
2.2.2 区分不同的响应视图
/**
 * @Description 简单视图展示View信息
 * @Author Mr.Gao
 */
public interface SimpleInfoView {
}

------ 视图与视图之间是可以继承的,那么也就实现既包含基础信息字段又包含需要的字段,进而实现不同DTO的返回 ---
/**
 * @Description 敏感信息
 * @Author Mr.Gao
 */
public interface SensitiveInfoView extends SimpleInfoView {
}

2.2.3 Controller 层的调用
/**
 * @Description 用户控制层
 * @Author Mr.Gao
 * @Date 2025/4/16 23:50
 */
@RestController
public class UserController {

    /**
     * 模拟从数据库获取用户信息
     *
     * @return
     */
    public static User getUserInfoFromDB() {
        User user = new User();
        user.setUsername("Mr.Gao");
        user.setAge(18);
        user.setSex("男");
        user.setMobileNo("12345678901");
        user.setLoginPwd("123456");
        user.setPayPwd("123456");
        return user;
    }

    /**
     * 获取用户简要信息
     *
     * @return
     */
    @JsonView(SimpleInfoView.class) // 返回简要信息的视图DTO
    @GetMapping("/user/getUserSimpleInfo")
    public User getUserSimpleInfo() {
        return getUserInfoFromDB();
    }

    /**
     * 获取用户详细信息
     *
     * @return
     */
    @JsonView(SensitiveInfoView.class)// 返回详情信息的视图DTO
    @GetMapping("/user/getUserDetailInfo")
    public User getUserDetailInfo() {
        return getUserInfoFromDB();
    }

}
2.2.4 简要信息 视图 DTO

在这里插入图片描述

2.2.5 详情信息 视图 DTO

在这里插入图片描述

2.3 问题已解决(引入原理实现篇)

经过上述代码案例操作,确实是可以解决我们后端程序猿的新建多个 DTO 对象的冗余问题,童鞋们可以都试试,但是出于好奇,为了什么在 一个实体对象 DTO 和 controller 层的方法 增加 @JsonView 注解之后就能实现不同视图的效果呢?其中究竟是使用了什么魔法呢?接下来我们继续进入 Debug 调试篇,继续 gank 它。

3、Debug调试篇

3.1 SpringMvc 切入点 对应的核心代码片段

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.2 字段属性序列化核心逻辑

在这里插入图片描述
在这里插入图片描述

经过上述分析可得,设置视图的核心代码为 objectMapper.writerWithView(serializationView) ,然后调用 objectMapper.writeValueAsString 方法是否可以实现不同视图的 DTO 输出呢?

3.3 多种 DTO 视图 Demo 验证

3.3.1 ObjectMapper 配置视图 View
@Test
public void testJsonViewAnnotationConvertMutiDTOByObjectMapper() throws JsonProcessingException {
    User user = UserController.getUserInfoFromDB();

    // @1: 设置序列化视图为SimpleInfoView(输出简要信息)
    objectMapper.setConfig(objectMapper.getSerializationConfig()
            .withView(SimpleInfoView.class));

    // @2: 设置序列化视图为SensitiveInfoView(输出详细信息)
    //objectMapper.setConfig(objectMapper.getSerializationConfig()
    //        .withView(SensitiveInfoView.class));

    System.out.println("采用Object序列化视图:" + objectMapper.getSerializationConfig().getActiveView());
    String JsonResult = objectMapper.writeValueAsString(user);
    System.out.println(JsonResult);
}
3.3.2 ObjectWriter 配置视图 View
@Test
public void testJsonViewAnnotationConvertMutiDTOByObjectWriter() throws JsonProcessingException {
    User user = UserController.getUserInfoFromDB();

    // @1: 设置序列化视图为SimpleInfoView(输出简要信息)
    //ObjectWriter objectWriter = objectMapper.writerWithView(SimpleInfoView.class);

    // @2: 设置序列化视图为SensitiveInfoView(输出详细信息)
    ObjectWriter objectWriter = objectMapper.writerWithView(SensitiveInfoView.class);

    System.out.println("ObjectWriter中的序列化视图为: " + objectWriter.getConfig().getActiveView());
    String JsonResult = objectWriter.writeValueAsString(user);
    System.out.println(JsonResult);
}

3.4 小结

最后,我本地的项目 SpringBoot 版本是 2.6.13,而我的 Pom 文件依赖中仅仅引入了spring-boot-starter-web,我可以确定的是没有引入任何 jackson 包的依赖的,而@JsonView 注解是 jackson 包下的注解,那么只有一种可能,那就是对应的 springboot 的 web 依赖集成了对应 jackson 相关 jar 包,出于好奇的我还是点开了 spring-boot-starter-web 依赖,结果发现确实是这样。
在这里插入图片描述

4、扩展点

4.1 ResponseBodyAdvice接口

对响应的内容可以进行二次包装处理,例如对响应参数内容统一进行签名、加密等逻辑处理。

4.2 RequestBodyAdvice接口

用来对请求的内容进行请求参数重写处理,例如对接收到请求参数统一进行验签、解密等逻辑处理。

综上所述,相信我们已经掌握了 如何通过一个 DTO 对象来渲染不同需求场景下的 DTO 对象,不过存在唯一的缺点,经过 Debug 调试篇我们可以发现,只有在 序列化的时候才会过滤对应的字段,那么如果一个 DTO 对象的属性太多,根据类的单一设计原则还是建议使用新建新的 DTO 对象来完成。所以我觉得可以视情况而定,想要代码的逻辑清晰一些就新建 DTO 实体,想要减少的代码的编码量(即减少 DTO 实体对象)那么就用@JsonView注解实现。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2338178.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

15 nginx 中默认的 proxy_buffering 导致基于 http 的流式响应存在 buffer, 以 4kb 一批次返回

前言 这也是最近碰到的一个问题 直连 流式 http 服务, 发现 流式响应正常, 0.1 秒接收到一个响应 但是 经过 nginx 代理一层之后, 就发现了 类似于缓冲的效果, 1秒接收到 10个响应 最终 调试 发现是 nginx 的 proxy_buffering 配置引起的 然后 更新 proxy_buffering 为…

安卓手机万能遥控器APP推荐

软件介绍 安卓手机也能当“家电总控台”?这款小米旗下的万能遥控器APP,直接把遥控器做成“傻瓜式操作”——不用配对,不连蓝牙,点开就能操控电视、空调、机顶盒,甚至其他品牌的电器!雷总这波操作直接封神&…

PH热榜 | 2025-04-18

1. Wiza Monitor 标语:跟踪工作变动,接收Slack和电子邮件的提醒。 介绍:Wiza Monitor是一款用于追踪职位变动的工具,可以实时跟踪客户和潜在客户的工作变动,还可以通过电子邮件和Slack发送提醒,让你的客户…

Android平台 Hal AIDL 系列文章目录

目录 1. Android Hal AIDL 简介2. AIDL 语言简介3. Android 接口定义语言 (AIDL)4. 定义AIDL 接口5. AIDL 中如何传递 Parcelable 对象6. 如何使用AIDL 定义的远程接口进行跨进程通信7. 适用于 HAL 的 AIDL8. Android Hal AIDL 编译调试9. 高版本Android (AIDL HAL) 沿用HIDL方…

十、数据库day02--SQL语句01

文章目录 一、新建查询1.查询窗口的开启方法2. 单语句运行方法 二、数据库操作1.创建数据库2. 使用数据库3. 修改数据库4. 删除数据库和查看所有数据库5. 重点:数据库备份5.1 应用场景5.2 利用工具备份备份操作还原操作 5.3 扩展:使用命令备份 三、数据表…

实时直播弹幕系统设计

整个服务读多写少,读写比例大概几百比1. 如果实时性要求高的话,可以采用长连接模式(轮询的话,时效性不好,同时对于评论少的直播间可能空转) websocket 和 SSE架构 只要求服务端推送的话,可以…

[Java · 初窥门径] Java 语言初识

🌟 想系统化学习 Java 编程?看看这个:[编程基础] Java 学习手册 0x01:Java 编程语言简介 Java 是一种高级计算机编程语言,它是由 Sun Microsystems 公司(已被 Oracle 公司收购)于 1995 年 5 …

【SQL Server】数据探查工具1.0研发可行性方案

👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 想抢先解锁数据自由的宝子,速速戳我!评论区蹲一波 “蹲蹲”,揪人唠唠你的超实用需求! 【SQL Server】数据探查工具1.0研发可行性方案…

谓词——C++

1.一元谓词 1.定义 2.案例 查找容器有没有大于五的数字 #include<stdio.h> using namespace std; #include<string> #include<vector> #include<set> #include <iostream> class myfind { public:bool operator()(int a){return a > 5;} …

『前端样式分享』联系我们卡片式布局 自适应屏幕 hover动效 在wikijs中使用 (代码拿来即用)

目录 预览效果分析要点响应式网格布局卡片样式&#xff1a;阴影和过渡效果 代码优化希望 长短不一的邮箱地址在左右居中的同时,做到左侧文字对齐(wikijs可用)总结 欢迎关注 『前端布局样式』 专栏&#xff0c;持续更新中 欢迎关注 『前端布局样式』 专栏&#xff0c;持续更新中…

MySQL 缓存机制全解析:从磁盘 I/O 到性能优化

MySQL 缓存机制全解析&#xff1a;从磁盘 I/O 到性能优化 MySQL 的缓存机制是提升数据库性能的关键部分&#xff0c;它通过多级缓存减少磁盘 I/O 和计算开销&#xff0c;从而提高查询和写入的效率。 1. 为什么需要缓存&#xff1f; 数据库的性能瓶颈通常集中在磁盘 I/O 上。…

1.1 设置电脑开机自动用户登录exe开机自动启动

本文介绍两个事情&#xff1a; 1.Windows如何开机自动登录系统&#xff08;不用输密码) 2. 应用程序(.exe)如何开机自动启动 详细解释如下&#xff1a; 一、Windows如何开机自动登录系统&#xff08;不用输密码) 设备上的工控机&#xff0c;如果开机后都需要操作人员输入密码&…

基于 Python 和 OpenCV 技术的疲劳驾驶检测系统(2.0 全新升级,附源码)

大家好&#xff0c;我是徐师兄&#xff0c;一个有着7年大厂经验的程序员&#xff0c;也是一名热衷于分享干货的技术爱好者。平时我在 CSDN、掘金、华为云、阿里云和 InfoQ 等平台分享我的心得体会。 &#x1f345;文末获取源码联系&#x1f345; 2025年最全的计算机软件毕业设计…

OpenAI重返巅峰:o3与o4-mini引领AI推理新时代

引言 2025年4月16日&#xff0c;OpenAI发布了全新的o系列推理模型&#xff1a;o3和o4-mini&#xff0c;这两款模型被官方称为“迎今为止最智能、最强大的大语言模型&#xff08;LLM&#xff09;”。它们不仅在AI推理能力上实现了质的飞跃&#xff0c;更首次具备了全面的工具使…

Unity3d 6(6000.*.*)版本国区下载安装参考

前言 Unity3d 6.是最新的版本&#xff0c;是与来自世界各地的开发者合作构建、测试和优化的成果&#xff0c;现在可以完全投入生产&#xff0c;是我们迄今为止性能最出色、最稳定的 Unity 版本。Unity 6 有许多令人兴奋的新工具和功能&#xff1a;端到端多人游戏工作流程将加速…

第 3 期:逆过程建模与神经网络的作用(Reverse Process)

一、从正向扩散到逆向去噪&#xff1a;生成的本质 在上期中我们讲到&#xff0c;正向扩散是一个逐步加入噪声的过程&#xff0c;从原始图像 x_0到接近高斯分布的 x_T​&#xff1a; 而我们真正关心的&#xff0c;是从纯噪声中逐步还原原图的过程&#xff0c;也就是逆过程&…

健康养生:开启活力生活新篇章

在当代社会&#xff0c;熬夜加班、久坐不动、外卖快餐成为许多人的生活常态&#xff0c;随之而来的是各种亚健康问题。想要摆脱身体的疲惫与不适&#xff0c;健康养生迫在眉睫&#xff0c;它是重获活力、拥抱美好生活的关键。​ 应对不良饮食习惯带来的健康隐患&#xff0c;饮…

记录学习的第二十九天

还是力扣每日一题。 本来想着像昨天一样两个循环搞定的&#xff0c;就下面&#x1f447;&#x1f3fb; 不过&#xff0c;结果肯定是超时啦&#xff0c;中等题是吧。 正确答案是上面的。 之后就做了ls题单第一部分&#xff0c;首先是定长滑窗问题 这种题都是有套路的&#xff0…

Express学习笔记(六)——前后端的身份认证

目录 1. Web 开发模式 1.1 服务端渲染的 Web 开发模式 1.2 服务端渲染的优缺点 1.3 前后端分离的 Web 开发模式 1.4 前后端分离的优缺点 1.5 如何选择 Web 开发模式 2. 身份认证 2.1 什么是身份认证 2.2 为什么需要身份认证 2.3 不同开发模式下的身份认证 3. Sessio…

leetcode 309. Best Time to Buy and Sell Stock with Cooldown

目录 题目描述 第一步&#xff0c;明确并理解dp数组及下标的含义 第二步&#xff0c;分析并理解递推公式 1.求dp[i][0] 2.求dp[i][1] 3.求dp[i][2] 第三步&#xff0c;理解dp数组如何初始化 第四步&#xff0c;理解遍历顺序 代码 题目描述 这道题与第122题的区别就是卖…