SpringBoot自定义JsonSerializer和JsonDeserializer,兼容LocalDateTime和LocalDate

news2024/9/20 20:27:07

1.前言

JDK1.8中添加新的时间日期API,LocalDate、LocalDateTime、LocalTime,但是我们在开发中使用时间戳作为参数值来传递是比较常用的,然而在SpringBoot中并没有为我们提供合适的JsonSerializer和JsonDeserializer。

我们先看看使用默认的Json序列化和反序列化器的情况,时间戳来自如下:

1.1 LocalDateTime返回值格式问题

@RestController
public class TestController {

    @GetMapping("/test")
    public DateDTO test() {
        DateDTO dateDTO = new DateDTO();
        dateDTO.setDateTime(LocalDateTime.now());
        return dateDTO;
    }

    @Data
    static class DateDTO {
        private LocalDateTime dateTime;
    }
}

请求参数:

curl --request GET \
  --url http://127.0.0.1:9999/test

响应参数:

{
    "code": 200,
    "msg": "success",
    "data": {
        "dateTime": "2023-02-12T17:57:03.7918033"
    }
}

这里LocalDateTime类型的属性的返回值格式,不是我们通用的时间戳格式,不利于前端同学格式化。

1.2 LocalDateTime请求参数问题

@RestController
public class TestController {

    @GetMapping("/test")
    public void test(@RequestBody DateDTO date) {
        System.out.println(date);
    }

    @Data
    static class DateDTO {
        private LocalDateTime dateTime;
    }
}

请求参数:

curl --request GET \
  --url http://127.0.0.1:9999/test \
  --header 'content-type: application/json' \
  --data '{
    "dateTime": 1676193312235
}'

当请求发送之后,系统直接报错了。看报错信息,意思是我们的参数值的格式不对,需要使用LocalDateTime的默认格式,例如:"2023-02-12T17:57:03.7918033",这样的话,前端同学在传值的时候就会比较麻烦

org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: raw timestamp (1676193312235) not allowed for `java.time.LocalDateTime`: need additional information such as an offset or time-zone (see class Javadocs); 

1.3 LocalDate请求参数问题

@RestController
public class TestController {

    @GetMapping("/test")
    public void test(@RequestBody DateDTO date) {
        System.out.println(date);
    }

    @Data
    static class DateDTO {
        private LocalDate date;
    }
}

请求参数:

curl --request GET \
  --url http://127.0.0.1:9999/test \
  --header 'content-type: application/json' \
  --data '{
    "date": 1676131200000
}'

当请求发送之后,系统直接报错了。看报错信息,提示我们传入的值超出了范围,其实我们传的就是毫秒级别的时间戳。

org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Invalid value for EpochDay (valid values -365243219162 - 365241780471): 1676131200000;

1.4 统一格式为时间戳

在SpringBoot中提供了@JsonComponent注解,可以直接帮我们注入JsonSerializerJsonDeserializer到Spring容器中,我们可以自定义将传参和返回值统一为时间戳。

接下来,我们来编写自定义的JsonSerializer以及JsonDeserializer

@JsonComponent
public class JsonConfig {

    public static class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
        @SneakyThrows
        @Override
        public void serialize(LocalDateTime value, JsonGenerator generator, SerializerProvider serializers) {
            generator.writeNumber(LocalDateTimeUtil.toEpochMilli(value));
        }
    }

    public static class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
        @Override
        public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
            String value = jsonParser.getText();
            // 约定传时间戳
            if (NumberUtil.isNumber(value)) {
                return LocalDateTimeUtil.of(Long.parseLong(value));
            } else {
                return DateUtil.parse(value).toLocalDateTime();
            }
        }
    }

    public static class LocalDateSerializer extends JsonSerializer<LocalDate> {
        @SneakyThrows
        @Override
        public void serialize(LocalDate value, JsonGenerator generator, SerializerProvider serializers) {
            generator.writeNumber(LocalDateTimeUtil.toEpochMilli(value));
        }

    }

    public static class LocalDateDeserializer extends JsonDeserializer<LocalDate> {
        @Override
        public LocalDate deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
            String value = jsonParser.getText();
            // 约定传时间戳
            if (NumberUtil.isNumber(value)) {
                return LocalDateTimeUtil.of(Long.parseLong(value)).toLocalDate();
            } else {
                return DateUtil.parse(value).toLocalDateTime().toLocalDate();
            }
        }
    }
}

现在我们来测试一下传参的格式:

@RestController
public class TestController {

    @GetMapping("/test")
    public DateDTO test(@RequestBody DateDTO date) {
        System.out.println(date);
        date.setDate(LocalDate.now());
        date.setDateTime(LocalDateTime.now());
        return date;
    }

    @Data
    static class DateDTO {
        private LocalDate date;
        private LocalDateTime dateTime;
    }
}

1.4.1 时间戳

请求参数:

curl --request GET \
  --url http://127.0.0.1:9999/test \
  --header 'content-type: application/json' \
  --data '{
    "date": 1676131200000,
    "dateTime": 1676198645075
}'

正常接收并返回:

{
    "code": 200,
    "msg": "success",
    "data": {
        "date": 1676131200000,
        "dateTime": 1676198792976
    }
}

1.4.2 正常时间格式

请求参数

curl --request GET \
  --url http://127.0.0.1:9999/test \
  --header 'content-type: application/json' \
  --data '{
    "date": "2023-02-12",
    "dateTime": "2023-02-12 09:00:00"
}'

正常接收并返回:

{
    "code": 200,
    "msg": "success",
    "data": {
        "date": 1676131200000,
        "dateTime": 1676199084811
    }
}

通过上面的处理,我们就实现了传参和返回值的统一。

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

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

相关文章

Linux根文件系统移植

目录 一、根文件系统 1.1根文件系统 1.2根文件系统内容 二、根文件系统移植 2.1BusyBox 2.2BusyBox的获取 2.3BusyBox的使用 2.4make menuconfig 2.5编译和安装 2.6修改根文件系统 一、根文件系统 1.1根文件系统 根文件系统是内核启动后挂载的第一个文件系统系统引…

Homekit智能家居创意DIY一智能灯

一、什么是智能灯 传统的灯泡是通过手动打开和关闭开关来工作。有时&#xff0c;它们可以通过声控、触控、红外等方式进行控制&#xff0c;或者带有调光开关&#xff0c;让用户调暗或调亮灯光。 智能灯泡内置有芯片和通信模块&#xff0c;可与手机、家庭智能助手、或其他智能…

链表题目总结 -- 递归

目录一. 递归反转整个链表1. 思路简述2. 代码3. 总结二. 反转链表前 N 个节点1. 思路简述2. 代码3. 总结三、反转链表的一部分1. 思路简述2. 代码3.总结四、反转链表后N个节点1. 思路简述2. 代码3.总结一. 递归反转整个链表 题目链接&#xff1a;https://leetcode.cn/problems…

部署智能合约到公链

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 &#x1f3c5;阿里云ACE认证高级工程师 &#x1f3c5;阿里云开发者社区专…

【面试】生命周期详情解释及案例

目录 1.什么是生命周期 2.生命周期函数 3.vue2中生命周期的函数 4.生命周期的阶段 5.生命周期图示 第一个阶段&#xff1a;组件创建阶段 第二个阶段&#xff1a;编译HTML模板并渲染到浏览器中 第三阶段&#xff1a;组件更新阶段 第四阶段&#xff1a;组件销毁阶段 1.什…

【数据结构】基础:图的基本概念与实现(附C++源代码)

【数据结构】基础&#xff1a;图的基本概念与实现&#xff08;附C源代码&#xff09; 摘要&#xff1a;将会在数据结构专题中开展关于图论的内容介绍&#xff0c;其中包括四部分&#xff0c;分别为图的概念与实现、图的遍历、图的最小生成树以及图的最短路径问题。本文将介绍图…

遗传算法(Genetic Algorithm,GA)实现数据排序,python

遗传算法(Genetic Algorithm,GA)实现数据排序&#xff0c;python 遗传算法是一种比较广泛、通用的算法体系&#xff0c;为了说明遗传算法的原理和实现&#xff0c;现在用GA解决一个计算机科学最基本、最古老的问题&#xff1a;排序问题。 需要特别说明的是&#xff0c;遗传算…

【GPLT 三阶题目集】L3-016 二叉搜索树的结构

二叉搜索树或者是一棵空树&#xff0c;或者是具有下列性质的二叉树&#xff1a; 若它的左子树不空&#xff0c;则左子树上所有结点的值均小于它的根结点的值&#xff1b;若它的右子树不空&#xff0c;则右子树上所有结点的值均大于它的根结点的值&#xff1b;它的左、右子树也分…

代码随想录LeetCode | 单调栈问题

前沿&#xff1a;撰写博客的目的是为了再刷时回顾和进一步完善&#xff0c;其次才是以教为学&#xff0c;所以如果有些博客写的较简陋&#xff0c;是为了保持进度不得已而为之&#xff0c;还请大家多多见谅。 预&#xff1a;看到题目后的思路和实现的代码。 见&#xff1a;参考…

两种特征提取方法与深度学习方法对比的小型金属物体分类分析研究

本文讨论了用于对包括螺丝、螺母、钥匙和硬币在内的小型金属物体进行分类的两种特征提取方法的效率&#xff1a;定向梯度直方图 (HOG) 和局部二进制模式 (LBP)。首先提取标记图像的所需特征并以特征矩阵的形式保存。使用三种不同的分类方法&#xff08;非参数 K 最近邻算法、支…

云计算|OpenStack|社区版OpenStack(实务操作---cloud-init的使用)

前言&#xff1a; 接上一篇文章&#xff1a;https://zskjohn.blog.csdn.net/article/details/128931042 我们可以从官方获取到现成的镜像&#xff0c;例如&#xff0c;从Ubuntu 18.04 LTS (Bionic Beaver) Daily Build [20230210]官方下载的bionic-server-cloudimg-amd64.img…

春招Leetcode刷题日记-D2-贪心算法-区间问题

D2-贪心算法-区间问题力扣435. 无重叠区间思路代码力扣435. 无重叠区间 题目链接&#xff1a;435. 无重叠区间 思路 1、贪心策略&#xff1a; 1、题目中&#xff0c;给了若干个区间&#xff0c;现在&#xff0c;我想留下尽可能多的&#xff0c;不重叠的区间 2、考虑&#…

Git配置多仓库账户密码

前言说明&#xff1a; 由于我们在工作中可能会遇到公司是用的gitlab仓库&#xff0c;代码下载需要github仓库&#xff0c;自己的项目需要gitee仓库&#xff0c;如何在同一台电电脑配置多个仓库账户密码就尤为重要。 (一) 配置流程 这里是在windows电脑上配置多仓库以github为例…

使用Spring框架的好处是什么

使用Spring框架的好处是什么&#xff1f; 1、轻量&#xff1a;Spring 是轻量的&#xff0c;基本的版本大约2MB。 2、控制反转&#xff1a;Spring通过控制反转实现了松散耦合&#xff0c;对象们给出它们的依赖&#xff0c;而不是创建或查找依赖的对象们。 3、面向切面的编程(AOP…

JCIM|Chemistry42:一个人工智能驱动的分子设计和优化平台

题目&#xff1a;Chemistry42: An AI-Driven Platform for Molecular Design and Optimization 文献来源&#xff1a;https://doi.org/10.1021/acs.jcim.2c01191 代码&#xff1a;https://insilico.com/pipeline (平台网址) 1.背景介绍 Chemistry42是Insilico Medicine提出…

Git_合并多次提交记录

Git_合并多次提交记录 前言&#xff1a;使用git rebase将多条提交记录合并成一条 应用场景&#xff1a;公司代码分支在master上&#xff0c;张三接到一个开发任务&#xff0c;需要在master上开发一个新功能&#xff0c;首先张三不能直接使用master分支进行开发&#xff0c;因为…

论文阅读:GeoAug: Data Augmentation for Few-Shot NeRF with Geometry Constrain

中文标题&#xff1a;使用几何约束增强小样本神经辐射场 提出的问题 NeRF尽管简介有效&#xff0c;但是往往不能收敛到正确的几何结构。这个问题在小样本学习中尤为明显&#xff0c;往往在没有足够训练数据的情况下&#xff0c;很难使得MLP网络学习到正确的几何的隐表示&#…

Solon Java Framework 2.1.2 发布。简单!高效!国产!

Solon 是一个高效的 Java 应用开发框架&#xff1a;更快、更小、更简单。它不是 Spring&#xff0c;没有用 Servlet&#xff0c;也无关 JavaEE&#xff1b;它也是一个新兴独立的开放生态。主框架仅 0.1 MB。 150来个生态插件&#xff0c;覆盖各种不同的应用开发场景&#xff1…

Linux Capabilities 入门

目录 Linux capabilities 是什么&#xff1f; capabilities 的赋予和继承 线程的 capabilities Permitted Effective Inheritable Bounding Ambient 文件的 capabilities Permitted Inheritable Effective 运行 execve() 后 capabilities 的变化 案例 Linux capab…

黑马】后台管理183-

一、添加时间线组件时间线组件在element2.6.0的版本中才可以找到项目中用到的插件早于时间线插件发布的&#xff0c;所以需要用到素材中的&#xff0c;timeline 和timeline-item复制到\code\shop-hou\src\plugins\1,在element.js中导入timeline等组件import Timeline from ./ti…