对后端返回的日期属性进行格式化(扩展 Spring MVC 的消息转换器)
格式化之前 格式化之后:
解决方式
方式一
在属性中加上注解,对日期进行格式化
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private LocalDateTime createTime;//@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private LocalDateTime updateTime;
方式二
在WebMvcConfiguration 中扩展Spring MVC的消息转换器,统一对日期类型进行格式化处理
扩展 Spring MVC 的消息转换器
/*** 扩展Spring MVC框架的消息转换器* @param converters*/@Overrideprotected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {//创建一个消息转换器对象MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();//需要为消息转换器设置一个对象转换器,对象转换器可以将Java对象序列化为json数据converter.setObjectMapper(new JacksonObjectMapper());//将自己的消息转换器加入容器中(因为converters拥有自带的消息转换器,所以设置索引为0可以优先使用自己的消息转换器)converters.add(0,converter);}
- extendMessageConverters 方法: 该方法允许开发者自定义 Spring MVC 的消息转换器。通过重写WebMvcConfigurationSupport中的这个方法,可以添加自定义的消息转换器。
-
@Override
: 注解表示这个方法重写了父类中的同名方法,这里是WebMvcConfigurationSupport
的extendMessageConverters
方法。 -
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters)
: 方法签名,接收一个List
类型的参数,包含所有当前注册的消息转换器。 -
创建一个新的MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
MappingJackson2HttpMessageConverter
实例。这个转换器用于将 Java 对象转换为 JSON 格式(序列化),以及将 JSON 数据转换为 Java 对象(反序列化)。 -
设置自定义的对象转换器(converter.setObjectMapper(new JacksonObjectMapper());
ObjectMapper
)。JacksonObjectMapper
是一个自定义类,通常是ObjectMapper
的一个扩展或配置版本。这样做的目的是让转换器使用特定的配置,例如序列化和反序列化的规则、日期格式等。 -
将自定义的消息转换器添加到转换器列表的第一个位置(索引为0)。这意味着在处理请求时,Spring 会优先使用这个自定义的转换器,而不是默认的转换器。确保你的自定义逻辑在系统的默认逻辑之前执行。converters.add(0, converter);
自定义 ObjectMapper(JacksonObjectMapper)对象转换器
package com.sky.json;import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;/*** 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象* 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]* 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]*/
public class JacksonObjectMapper extends ObjectMapper {public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";//public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";public JacksonObjectMapper() {super();//收到未知属性时不报异常this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);//反序列化时,属性不存在的兼容处理this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);SimpleModule simpleModule = new SimpleModule().addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT))).addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT))).addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT))).addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT))).addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT))).addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));//注册功能模块 例如,可以添加自定义序列化器和反序列化器this.registerModule(simpleModule);}
}
-
JacksonObjectMapper: 这个类继承自
ObjectMapper
,用于自定义 JSON 的序列化和反序列化规则。 -
日期时间格式常量:
DEFAULT_DATE_FORMAT
: 定义了默认日期格式(yyyy-MM-dd
)。DEFAULT_DATE_TIME_FORMAT
: 定义了默认日期时间格式(yyyy-MM-dd HH:mm
)。DEFAULT_TIME_FORMAT
: 定义了默认时间格式(HH:mm:ss
)。
-
构造函数:
this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false)
: 配置 Jackson,使其在遇到未知属性时不抛出异常。这有助于增强反序列化的灵活性。this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
: 进一步确保在反序列化时忽略未知属性。
-
SimpleModule: 创建并注册一个模块,指定如何处理 Java 8 日期和时间 API 类型的序列化与反序列化。
- 使用
addDeserializer()
方法,定义如何将 JSON 中的日期时间字段解析为 Java 对象。 - 使用
addSerializer()
方法,定义如何将 Java 对象序列化为 JSON。
- 使用
-
registerModule(simpleModule): 注册自定义的模块,使得 Jackson 能够使用定义的序列化和反序列化器。
CBOR详解
CBOR(Concise Binary Object Representation)是一种二进制数据格式,主要用于数据序列化和反序列化。它是为了提供一种比 JSON 更高效的方式来编码数据,以满足现代应用程序对性能和存储空间的需求。
CBOR 的特点
-
紧凑性:
CBOR 使用二进制格式,通常比文本格式(如 JSON)占用更少的空间。这使得它在网络传输和存储时更加高效。 -
高效性:
由于 CBOR 是二进制格式,解析速度通常比文本格式快,因为它避免了字符串解析所需的额外处理。 -
灵活的数据类型:
CBOR 支持多种数据类型,包括:- 布尔值和空值
- 映射(键值对)
- 数组
- 字符串(文本和二进制)
- 浮点数
- 整数(正整数和负整数)
-
与 JSON 兼容:
CBOR 能够表示 JSON 所有的数据结构,这使得它在需要与 JSON 互操作时非常方便。 -
自描述性:
CBOR 数据包含类型信息,接收方可以根据这些信息理解数据的结构,减少了解析时的复杂性。 -
扩展性:
CBOR 允许用户定义扩展类型,可以根据特定的需求添加新的数据类型。
CBOR 的结构
CBOR 数据的基本构成是由一系列的标签、类型标识符和具体数据组成。每个数据项都有一个类型标识符,指示数据的类型。例如:
- 整数: 0 到 23 用单字节表示,超过这个范围则使用多个字节。
- 浮点数: 支持半精度和单精度浮点数。
- 字符串: 可以是 UTF-8 编码的文本或二进制数据。
- 数组和映射: 分别用于表示有序和无序的数据集合。
应用场景
-
物联网(IoT): 在带宽有限的环境中,CBOR 的紧凑性能够显著提高数据传输效率。
-
网络通信: 特别是在快速响应和低延迟的应用中,CBOR 提供了更好的性能。
-
存储系统: 适合用于大规模数据存储,因其占用空间小且读写效率高。
-
API 和微服务: CBOR 可用于后端服务之间的数据交换,特别是在 JSON 交互频繁的场合。
总结
CBOR 是一种现代、高效的序列化格式,适用于各种需要高性能和低带宽的应用场景。通过其紧凑的二进制表示和灵活的数据结构,CBOR 为开发者提供了处理数据的新工具,尤其是在物联网、网络通信和存储系统等领域。
示例数据
假设我们有一个简单的字典对象,内容如下:
{"name": "Alice","age": 30,"isStudent": false,"courses": ["Math", "Science"],"grades": {"Math": 90,"Science": 85}
}
转换为 CBOR
将上述 JSON 数据转换为 CBOR 格式后,它的二进制表示可能类似于以下内容(注意:实际的二进制数据会因实现而异,以下为示意):
A5 67 6E 61 6D 65 61 6C 69 63 18 1E 67 61 67 65 30 1E 69 73 53 74 75 64 65 6E 74 6E 65 02 81 04 67 43 6F 75 72 73 82 64 4D 61 74 68 64 39 6D 61 74 68 64 35 53 63 69 65 6E 63 65 38 35
这里的每一段数据代表了 JSON 中的不同部分,例如名称、年龄、课程等。
使用 CBOR 库
在实际编码和解码过程中,可以使用库来处理 CBOR 数据。在 Python 中,我们可以使用 cbor2
库来实现:
import cbor2# 原始数据
data = {"name": "Alice","age": 30,"isStudent": False,"courses": ["Math", "Science"],"grades": {"Math": 90,"Science": 85}
}# 编码为 CBOR
cbor_data = cbor2.dumps(data)# 解码回原始数据
decoded_data = cbor2.loads(cbor_data)print(decoded_data) # 输出: {'name': 'Alice', 'age': 30, 'isStudent': False, 'courses': ['Math', 'Science'], 'grades': {'Math': 90, 'Science': 85}}
总结
CBOR 是一种高效的二进制数据格式,适合用于需要快速解析和较小数据占用的场景。通过示例可以看到,如何从 JSON 数据转换为 CBOR,以及如何使用库进行编码和解码。
相关文章:

对后端返回的日期属性进行格式化(扩展 Spring MVC 的消息转换器)
格式化之前 格式化之后: 解决方式 方式一 在属性中加上注解,对日期进行格式化 JsonFormat(pattern "yyyy-MM-dd HH:mm:ss")private LocalDateTime createTime;//JsonFormat(pattern &quo…...

踩坑记录-用python解析php Laravel8生成的jwt token一直提示 Invalid audience
import jwtdef token_required(token):with open(storage/oauth-public.key, r) as f:public_key f.read()try:# 尝试使用当前算法解码 token,同时指定受众decoded jwt.decode(token, public_key, algorithms[RS256], options{"verify_aud": False})# p…...

使用IOT-Tree Server制作一个边缘计算设备(Arm Linux)
最近实现了一个小项目,现场有多个不同厂家的设备,用户需要对此进行简单的整合,并实现一些联动控制。 我使用了IOT-Tree Server这个软件轻松实现了,不外乎有如下过程: 1)使用Modbus协议对接现有设备&#…...

(JAVA)B树和B+树的实现原理阐述
1. B 树 2-3树中,一个节点最多能有两个key,它的实现红黑树中适用对链接染色的方式去表达这两个key。下面将学习另一种树形结构B树,这种数据结构中,一个节点允许多余两个key的存在。 B树是一种树状数据结构,它能够存储…...

JC系列CAN通信说明
目录 一、CAN协议二、指令格式三、通信接线3.1、一对一通信3.2、组网通信 四、寄存器定义五、指令说明4、读取电源电压5、读取母线电流6、读取实时速度8、读取实时位置10、读取驱动器温度11、读取电机温度12、读取错误信息32、设定电流33、设定速度35、设定绝对位置37、设定相对…...

Ubuntu22——安装并配置局域网文件共享系统Samba
我们将共享目录设置为 /home/takway/share。以下是基于这个新目录的详细步骤: 在Ubuntu上安装并配置Samba 更新系统包列表 打开终端,执行以下命令来确保你的包列表是最新的: sudo apt update安装Samba 安装Samba及其相关工具: sud…...

HTML CSS 基础
HTML & CSS 基础 HTML一、HTML简介1、网页1.1 什么是网页1.2 什么是HTML1.3 网页的形成1.4总结 2、web标准2.1 为什么需要web标准2.2 Web 标准的构成 二、HTML 标签1、HTML 语法规范1.1基本语法概述1.2 标签关系 2、 HTML 基本结构标签2.1 第一个 HTML 网页2.2 基本结构标签…...

Nginx 使用 GeoIP 模块阻止特定国家 IP 地址的最佳实践
一、概述 为什么要阻止特定国家的 IP 地址? 在全球化的互联网上,网站和服务器可能会面对来自不同国家和地区的用户流量。虽然大多数情况下,我们希望网站能为全球用户提供服务,但在某些特定场景下,阻止来自特定国家的…...

vue3 + vite + cesium项目
GitHub - tingyuxuan2302/cesium-vue3-vite: 项目基于 vue3 vite cesium,已实现常见三维动画场,欢迎有兴趣的同学加入共建,官网服务器相对拉胯,请耐心等候...https://github.com/tingyuxuan2302/cesium-vue3-vite/tree/github...

DR模式 LVS负载均衡群集
DR模式 LVS负载均衡群集 部署共享存储关闭防火墙和核心防护下载,开启nfs服务创建共享文件夹和测试用的静态网页文件编辑nfs配置文件发布共享查看共享 配置 tomcat 服务器关闭防火墙和核心防护安装tomcat配置 tomcat 多实例 配置 nginx 服务器关闭防火墙和核心防护配…...

mysql复制表结构和数据
1.实例 #复制一张和test 一摸一样的表结构 CREATE TABLE test_one like test#往复制的表结构中复制数据 INSERT INTO test_one SELECT * FROM test#两者一起使用相当于 cv大法2.总结 完全实现了表结构和数据的复制,但是两条sql 得分两步执行 2.1 复制表结构 #复制…...

MFC扩展库BCGControlBar Pro v35.1新版亮点:改进网格控件性能
BCGControlBar库拥有500多个经过全面设计、测试和充分记录的MFC扩展类。 我们的组件可以轻松地集成到您的应用程序中,并为您节省数百个开发和调试时间。 BCGControlBar专业版 v35.1已全新发布了,这个版本改进网格控件的性能、增强工具栏编辑器功能等。 …...

Python列表操作详解
1 列表的基本概念 在Python中,列表是一种非常常用的数据结构,它可以存储任意类型的元素,并且支持多种操作。下面将详细介绍Python列表的各种操作。 2列表的操作方法 2.1创建列表 Python可以直接使用方括号[]来创建一个空列表。 示例&am…...

畅捷通T+对接聚水潭成功实施案例
在当今竞争激烈的商业环境中,企业数字化转型已成为提升竞争力的关键。广东某实业有限公司的数字化规划,目前财务系统使用的畅捷通T,电商系统使用的聚水潭。目前两个系统数据割裂导致各个部门的协同效率低下。通过借助轻易云数据集成平台&…...

leetcode-312. 戳气球
题目描述 有 n 个气球,编号为0 到 n - 1,每个气球上都标有一个数字,这些数字存在数组 nums 中。 现在要求你戳破所有的气球。戳破第 i 个气球,你可以获得 nums[i - 1] * nums[i] * nums[i 1] 枚硬币。 这里的 i - 1 和 i 1 代…...

程序设计基础I-实验7 函数(编程题)
7-1 sdut- C语言实验—计算表达式 计算下列表达式值: 输入格式: 输入x和n的值,其中x为非负实数,n为正整数。 输出格式: 输出f(x,n),保留2位小数。 输入样例: 3 2输出样例: 在这里给出相应的输出。例如: 2.00 …...

使用3080ti配置安装blip2
使用3080ti运行blip2的案例 本机环境(大家主要看GPU,ubuntu版本和cuda版本即可):安装流程我最后安装的所有包的信息(python 3.9 )以供参考(environment.yml): 本机环境&a…...

vue3组件通信之defineEmits
一、defineEmits是什么? defineEmits 是vue3提供的方法,又称为自定义事件,不需要引入可以直接使用,用于子组件与父组件通信。 二、使用样例 1.父组件代码 代码如下(示例): <template>…...

rust gio-rs 挂载 samba 磁盘
linux 使用的 gio 管理工具 这个工具如下 这是 gio 的rust版本 https://crates.io/crates/gio 可以用 rust 语言实现下面所有操作 gio mout 挂载 samba 如下 //https://valadoc.org/gio-2.0/GLib.MountOperation.html pub async fn gio_mount(uri路径:&str, 用户名:Opti…...

幸存者游戏(类)
#include <iostream> #include <graphics.h> #include <stdio.h> #include <conio.h> #include <vector> #include <string> using namespace std; int idx_player_anim 0; const int player_anim_num 6;//这里要把动画帧数定位const i…...

SQL 中UPDATE 和 DELETE 语句的深入理解与应用
在 SQL 中,UPDATE和DELETE语句是用于操作表数据的重要工具,它们允许我们对已存在的数据进行修改和删除。 一、UPDATE 语句 (一)基本语法 UPDATE语句的基本语法如下: UPDATE table_name SET column1 value1, colum…...

在 Windows 上查找和结束占用特定端口占用程序,并杀死
在 Windows 上查找和结束占用特定端口(如 9003)的程序,你可以使用以下步骤: 步骤 1:找到占用端口的进程 ID (PID) 打开命令提示符(按 Win R,输入 cmd,然后按回车)。输…...

sql server尽量避免滥用影响性能的标量函数
相信很多新手学了 函数的用法就不可避免的想把学到的东西用起来,然而这个函数使用却有坑, 在实际用的时候我发现一个简单的计算封装 ,不用函数和用函数执行耗时差太多了。 能避免列上进行函数则尽量避免,这是在实际上遇到的坑 &am…...

python画图|二维动态柱状图输出
【1】引言 在前面的学习过程中,已经探索过二维柱状图和三维柱状图的绘制教程,包括且不限于的文章链接有: python画图|水平直方图绘制_绘制水平直方图-CSDN博客 python画图|3D bar进阶探索_ax.bar3d-CSDN博客 此外也学习了动态的直线输出和…...

CocosCreator 快速部署 TON 游戏:Web2 游戏如何使用 Ton支付
在本篇文章中,我们将继续探讨如何使用 Cocos Creator 开发 Telegram 游戏,重点介绍如何集成 TON 支付功能。通过这一教程,开发者将学会如何在游戏中接入 TON Connect,实现钱包连接、支付以及支付后的校验流程,最终为 W…...

生信初学者教程(二十八):单细胞数据标准化
文章目录 介绍加载R包导入数据消除测序深度影响评估细胞周期的影响识别高度可变的特征缩放数据降维聚类输出结果总结介绍 scRNA-seq的标准化是一个重要的预处理步骤,目的是消除技术变异(比如比如测序深度和基因长度等因素),使基因表达和/或样本之间的比较更加可靠。标准化方…...

【OceanBase诊断调优】—— 错误码 5065 和 5066 的区别
适用版本:V2.1.x、V2.2.x、V3.1.x、V3.2.x 5065 与 5066 是两个近似的报错。 OB_ERR_QUERY_INTERRUPTED(-5065): Message: Query execution was interrupted。 含义为执行中断, 例如终端执行 SQL 过程中按 ctrlc 终止 SQL 执行会报 -5065。 OB_ERR_SESSION_INTER…...

Spring Boot RESTful API开发教程
一、RESTful API简介 RESTful API是一种基于HTTP协议的Web API,其设计原则是简单、可扩展、轻量级、可缓存、可靠、可读性强。RESTful API通常使用HTTP请求方法(GET、POST、PUT、DELETE等)来操作资源,使用HTTP状态码来表示操作结…...

<Rust>iced库(0.13.1)学习之番外:如何为窗口添加初始值?
前言 本专栏是学习Rust的GUI库iced的合集,将介绍iced涉及的各个小部件分别介绍,最后会汇总为一个总的程序。 iced是RustGUI中比较强大的一个,目前处于发展中(即版本可能会改变),本专栏基于版本0.12.1. 注:新版本已更新为0.13 概述 这是本专栏的番外篇,主要介绍一下新…...

Redis:list类型
Redis:list类型 list命令非阻塞LPUSHLRANGELPUSHXRPUSHRPUSHXLPOPRPOPLINDEXLINSERTLLENLREMLTRIMLSET 阻塞BLPOPBRPOP 内部编码ziplistlinkedlistquicklist 几乎每种语言都有顺序表、数组、链表这样的顺序结构,Redis也做出了相应的支持。 如图ÿ…...