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

@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.mzph.cn/bicheng/77605.shtml

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

相关文章

Etcd 压缩整理

etcd数据存储 在实际生产中使用 ETCD 存储元数据,起初集群规模不大的时候元数据信息不多没有发现什么问题。随着集群规模越来越大,可能引发存储问题。 —auto-compaction-retention 由于ETCD数据存储多版本数据,随着写入的主键增加历史版本需…

【更新完毕】2025妈妈杯C题 mathercup数学建模挑战赛C题数学建模思路代码文章教学:音频文件的高质量读写与去噪优化

完整内容请看文章最下面的推广群 我将先给出文章、代码、结果的完整展示, 再给出四个问题详细的模型 面向音频质量优化与存储效率提升的自适应编码与去噪模型研究 摘 要 随着数字媒体技术的迅速发展,音频处理技术在信息时代的应用愈加广泛,特别是在存储…

React-请勿在循环或者条件语句中使用hooks

这是React Hooks的首要规则,这是因为React Hooks 是以单向循环链表的形式存储,即是有序的。循环是为了从最后一个节点移到一个节点的时候,只需通过next一步就可以拿到第一个节点,而不需要一层层回溯。React Hooks的执行&#xff0…

【大模型】 LangChain框架 -LangChain实现问答系统

LangChain 介绍与使用方法 1. 什么是 LangChain?2. LangChain 的主要功能3. 如何使用 LangChain?3.1 环境准备3.2 基本使用示例3.2.1 简单的问答系统3.2.2 结合外部工具 3.3 高级用法 4. 常见问题及解决方法4.1 安装问题4.2 运行问题4.3 性能问题 5. 实战…

企业级HAProxy高可用离线部署实战(附Kubernetes APIServer负载均衡配置)

企业级HAProxy高可用离线部署实战(附Kubernetes APIServer负载均衡配置) 摘要:本文深入讲解在离线环境下部署HAProxy 3.1.1的全流程,涵盖源码编译、系统服务封装、K8S APIServer四层负载配置等核心环节,并提供生产级高…

Python网络爬虫设计(一)

目录 一、网络爬虫 1、基本的爬虫 2、获取URL 3、查找网页源码关键字 4、代码实现 二、requests库 1、requests的优势和劣势 2、获取网页的其他库 (1)selenium库 (2)pyppeteer库 三、pyppeteer库 1、pyppeteer库的来历…

BR_频谱20dB 带宽(RF/TRM/CA/BV-05-C [TX Output Spectrum – 20 dB Bandwidth])

目录 一、规范要求 1、协议章节 2、测试目的 二、测试方法 1、样机初值条件: 2、测试步骤: 方法一:频谱仪 方法二:综测仪CMW500 3、预期结果 一、规范要求 1、协议章节 4.5.5 RF/TRM/CA/BV-05-C [TX Output Spectrum – 20 dB Ba…

【橘子大模型】初探rag知识库的构建

一、简介 我们在实现了一系列功能之后,终于来到了rag的部分,下面我们将基于langchain来实现一个rag检索。 关于rag方面的知识,可以查看这两篇文章: 大模型应用之RAG详解 什么是 RAG(检索增强生成) 或者是去…

CentOS7执行yum命令报错 Could not retrieve mirrorlist http://mirrorlist.centos.org

CentOS7执行yum命令报错 引更新yum源备份原有源创建新的源文件清理并重建缓存 引 CentOS 7 系统无法连接到 CentOS 的官方镜像站点。这通常是由于网络问题或 CentOS 7 已停止维护导致的(2024年6月30日后 CentOS 7 已进入 EOL) 报错明细: 已…

VSCode安装与环境配置(Mac环境)

20250419 - 概述 大概是非常久之前了,装了VSCode,估计都得21的时候了,电脑上也没更新过。当时安装也直接装上就完事了。这次把版本更新一下,同时记录一下这个安装过程。 安装 mac下安装非常简单,直接从官网下载&am…

QML动画--ParallelAnimation和SequentialAnimation

一、ParallelAnimation ParallelAnimation 是 QML 中用于并行执行多个动画的容器动画类型,可以同时运行多个子动画。 基本用法 qml import QtQuick 2.15Rectangle {id: rectwidth: 100; height: 100color: "red"x: 0; y: 0; opacity: 1.0ParallelAnim…

NLP高频面试题(四十三)——什么是人类偏好对齐中的「对齐税」(Alignment Tax)?如何缓解?

一、什么是「对齐税」(Alignment Tax)? 所谓「对齐税」(Alignment Tax),指的是在使人工智能系统符合人类偏好的过程中,所不可避免付出的性能损失或代价。换句话说,当我们迫使AI遵循人类价值观和规范时,AI系统往往无法达到其最大理论性能。这种性能上的妥协和折衷,就…

速查手册:TA-Lib 超过150种量化技术指标计算全解 - 1. Overlap Studies(重叠指标)

速查手册:TA-Lib 超过150种量化技术指标计算全解 - 1. Overlap Studies(重叠指标) TA-Lib(Technical Analysis Library)是广泛使用的金融技术分析库,实现了超过150种技术指标计算函数,适用于股票…

重构未来智能:Anthropic 解码Agent设计哲学三重奏

第一章 智能体进化论:从工具到自主体的认知跃迁 1.1 LLM应用范式演进图谱 阶段技术形态应用特征代表场景初级阶段单功能模型硬编码规则执行文本摘要/分类进阶阶段工作流编排多模型协同调度跨语言翻译流水线高级阶段自主智能体动态决策交互编程调试/客服对话 1.1.…

Git 中修改某个特定的commit提交内容

在 Git 中修改某个特定的提交(commit)通常需要使用 交互式变基(Interactive Rebase) 或 修改提交(Commit Amend)。以下是不同场景下的具体操作步骤: 一、修改最近的提交(最新提交&am…

ZLMediaKit流媒体服务器

ZLMediaKit 简介 ZLMediaKit 是一个基于 C11 开发的高性能流媒体服务器框架,支持 RTSP、RTMP、HLS、HTTP-FLV、WebSocket-FLV、HTTP-TS、WebSocket-TS、HTTP-fMP4、WebSocket-fMP4 等多种流媒体协议。 主要特性 多协议支持: 支持 RTSP/RTMP/HLS/HTTP-F…

数字电子技术基础(五十)——硬件描述语言简介

目录 1 硬件描述语言简介 1.1 硬件描述语言简介 1.2 硬件编程语言的发展历史 1.3 两种硬件描述的比较 1.4 硬件描述语言的应用场景 1.5 基本程序结构 1.5.1 基本程序结构 1.5.2 基本语句和描述方法 1.5.3 仿真 1 硬件描述语言简介 1.1 硬件描述语言简介 硬件描述语…

SQL系列:常用函数

1、【MySQL】合并字段函数(列转行) 它可以将两个字段中的数据合并到一个字段中。 1)CONCAT函数 CONCAT函数可以将多个字段中的数据合并到一个字段中。它的语法格式如下: SELECT CONCAT(字段1,字段2,...字段N) FROM 表名;SELEC…

多线程和线程同步

多线程在项目开发中使用频率高,使用多线程能够提高程序的并发性 提高程序的并发性:1.多线程,对系统资源的消耗更小一些 2.多进程 系统的cpu资源有线,cpu时间片被分好后,由系统进行调度,每个线程在执行的时候都需要抢这个cpu的时间片。如果抢到了,就执行,如果没抢到,…

时序数据预测:TDengine 与机器学习框架的结合(一)

一、引言 在当今数字化时代,时序数据如潮水般涌来,广泛存在于物联网、工业监控、金融交易、气象监测等众多领域。这些按时间顺序记录的数据蕴含着丰富的信息,对其进行准确预测,能够为企业和组织的决策提供有力支持,带…