Jaskson精讲第6篇-自定义JsonSerialize与Deserialize实现数据类型转换

Jackson是Spring Boot(SpringBoot)默认的JSON数据处理框架,但是其并不依赖于任何的Spring 库。有的小伙伴以为Jackson只能在Spring框架内使用,其实不是的,没有这种限制。它提供了很多的JSON数据处理方法、注解,也包括流式API、树模型、数据绑定,以及复杂数据类型转换等功能。它虽然简单易用,但绝对不是小玩具,更多的内容我会写成一个系列,5-10篇文章,请您继续关注我。
- 《序列化与反序列化核心用法-JSON框架Jackson精解第1篇》
- 《特殊数据格式处理-JSON框架Jackson精解第2篇》
- 《属性序列化自定义排序与字母表排序-JSON框架Jackson精解第3篇》
- 《@JacksonInject与@JsonAlias注解-JSON框架Jackson精解第4篇》
- 《@JsonCreator自定义反序列化函数-JSON框架Jackson精解第5篇》
本节继续为大家介绍在Jackson序列化中经常遇到的一些特殊的数据类型,如LocalDateTime 。该如何进行序列化和反序列化。
一、LocalDateTime反序列化异常
首先我们定义一个java POJO实体类,其中关键的成员变量时birthDate,我们没有采用Date数据类型,而是采用了Java8 新的日期类型LocalDateTime ,使用LocalDateTime 的好处我就不多说了,有很多的文章解释说明。我们把精力放回到Jackson的JSON格式序列化与反序列化内容上来。
@Data
public class PlayerStar4 {
private String name; //姓名
private LocalDateTime birthDate; //出生日期
}
下面的代码,我们首先定义了一个PlayerStar4类的对象player,然后
- 使用writeValueAsString方法将player对象序列化为JSON字符串jsonString
- 然后使用readValue方法将JSON字符串jsonString ,反序列化为PlayerStar4类的对象
@Test
void testJSON2Object() throws IOException {
ObjectMapper mapper = new ObjectMapper();
PlayerStar4 player = new PlayerStar4();
player.setName("curry");//我并不知道库里的生日,这里是编造的
player.setBirthDate(LocalDateTime.of(1986,4,5,12,50));
//将player对象以JSON格式进行序列化为String对象
String jsonString = mapper.writeValueAsString(player);
System.out.println(jsonString);
//将JSON字符串反序列化为java对象
PlayerStar4 curry = mapper.readValue(jsonString, PlayerStar4.class);
System.out.println(curry);
}
但是上面的代码报错了,从下图中可以看出
- 将player对象序列化为JSON字符串jsonString 的过程被正常执行了,但是LocalDateTime序列化之后的结果,是图中”黄框中的黄框“内容。
- 将JSON字符串反序列化的过程报错了,因为Jackson默认情况下,根本不认识图中”黄框中的黄框“内容这种LocalDateTime序列化之后的JSON字符串数据结构。无法把它反序列化为java对象。

怎么办?我们需要自定义序列化及反序列化类型转换器,有两种方法
- 继承StdConverter类,自定义实现String与LocalDateTime相互转换
- 继承JsonSerializer和JsonDeserializer类,自定义实现String与LocalDateTime相互转换
二、方法一:继承StdConverter类
继承StdConverter类,将LocalDateTime序列化为String数据类型
public class LocalDateTimeToStringConverter extends StdConverter<LocalDateTime, String> {
static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
@Override
public String convert(LocalDateTime value) {
return value.format(DATE_FORMATTER);
}
}
继承StdConverter类,将String数据类型反序列化为LocalDateTime
public class StringToLocalDatetimeConverter extends StdConverter<String, LocalDateTime> {
@Override
public LocalDateTime convert(String value) {
return LocalDateTime.parse(value, LocalDateTimeToStringConverter.DATE_FORMATTER);
}
}
自定义的转换器完成之后,我们就可以在对应的成员变量上,使用@JsonSerialize指定序列化转换器,@JsonDeserialize指定反序列化转换器。
@JsonSerialize(converter = LocalDateTimeToStringConverter.class)
@JsonDeserialize(converter = StringToLocalDatetimeConverter.class)
private LocalDateTime birthDate;
然后调用第一小节中的测试用例,就不会出现异常了。控制台打印输出结果如下,第一行是序列化结果JSON格式字符串,第二行是Java 对象的toString()方法的打印结果。
{"name":"curry","birthDate":"1986-4-5 12:50:00"}
PlayerStar4(name=curry, birthDate=1986-04-05T12:50)
三、方法二:继承JsonSerializer和JsonDeserializer类
继承JsonSerializer<LocalDateTime>类,将LocalDateTime序列化为String数据类型
public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
@Override
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider provider)
throws IOException {
String s = value.format(DATE_FORMATTER);
gen.writeString(s);
}
}
继承JsonDeserializer<LocalDateTime>类,将String数据类型反序列化为LocalDateTime
public class LocalDatetimeDeserializer extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctx)
throws IOException {
String str = p.getText();
return LocalDateTime.parse(str, LocalDateTimeSerializer.DATE_FORMATTER);
}
}
四、如果上面的你都没看懂
对于相对小白的读者,上面的自定义序列化及反序列化转换过程你都没懂,对于LocalDateTime的异常你也不要慌,Jackson已经给出了解决方案。
需要特别和大家强调的是LocalDateTimeSerializer和LocalDateTimeDeserializer其实并不需要我们自己去定义,因为Jackson已经帮我们定义好了。 之所以我还做了自定义的实现的介绍,是因为要为大家讲解这个自定义序列化和反序列化类型转换的实现过程,以后你再遇到其他的特殊的数据类型转换,或者LocalDateTime类型的特殊日期格式等,都可以自己来定义JsonSerialize和JsonDeserialize来实现数据类型的转换。
下面的这两个类就是Jackson已经帮我们定义好的LocalDateTimeSerializer和LocalDateTimeDeserializer。
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
使用方法是在对应的成员变量上,使用@JsonSerialize指定序列化转换器,@JsonDeserialize指定反序列化转换器。
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime birthDate;
执行之后的序列化和反序列化结果,和方法一、方法二自定义的实现效果是一样的。
欢迎关注我的博客,里面有很多精品合集
- 本文转载注明出处(必须带连接,不能只转文字):字母哥博客。
觉得对您有帮助的话,帮我点赞、分享!您的支持是我不竭的创作动力! 。另外,笔者最近一段时间输出了如下的精品内容,期待您的关注。
- 《手摸手教你学Spring Boot2.0》
- 《Spring Security-JWT-OAuth2一本通》
- 《实战前后端分离RBAC权限管理系统》
- 《实战SpringCloud微服务从青铜到王者》
- 《VUE深入浅出系列》
Jaskson精讲第6篇-自定义JsonSerialize与Deserialize实现数据类型转换的更多相关文章
- Jaskson精讲第7篇-类继承关系下的JSON序列化与反序列化JsonTypeInfo
Jackson是Spring Boot(SpringBoot)默认的JSON数据处理框架,但是其并不依赖于任何的Spring 库.有的小伙伴以为Jackson只能在Spring框架内使用,其实不是的, ...
- 转 Redis 总结精讲 看一篇成高手系统-4
转 Redis 总结精讲 看一篇成高手系统-4 2018年05月31日 09:00:05 hjm4702192 阅读数:125633 本文围绕以下几点进行阐述 1.为什么使用redis 2.使用r ...
- Java岗 面试考点精讲(基础篇01期)
即将到来金三银四人才招聘的高峰期,渴望跳槽的朋友肯定跟我一样四处找以往的面试题,但又感觉找的又不完整,在这里我将把我所见到的题目做一总结,并尽力将答案术语化.标准化.预祝大家面试顺利. 术语会让你的面 ...
- Java岗 面试考点精讲(网络篇03期)
1. OSI七层模型 总结一下: 应用用层按协议打包数据 由传输层加上双方的端口号 由网络层加上双方的IP地址 由链路层加上双方的MAC地址,并将数据拆分成数据帧 数模信号转换并由物理层传输到另一端 ...
- Java岗 面试考点精讲(基础篇02期)
1. 两个对象的hashCode相同,则equals也一定为true,对吗? 不对,答案见下面的代码: @Override public int hashCode() { return 1; } 两个 ...
- Redis 总结精讲 看一篇成高手系统-4
本文围绕以下几点进行阐述 1.为什么使用redis2.使用redis有什么缺点3.单线程的redis为什么这么快4.redis的数据类型,以及每种数据类型的使用场景5.redis的过期策略以及内存淘汰 ...
- 【转】Redis 总结精讲 看一篇成高手系统-4
https://www.cnblogs.com/rjzheng/p/9096228.html 本文围绕以下几点进行阐述 1.为什么使用redis2.使用redis有什么缺点3.单线程的redis为什么 ...
- Redis 总结精讲 看一篇成高手系统4
本文围绕以下几点进行阐述 1.为什么使用redis2.使用redis有什么缺点3.单线程的redis为什么这么快4.redis的数据类型,以及每种数据类型的使用场景5.redis的过期策略以及内存淘汰 ...
- Redis 总结精讲 看一篇成高手系统
转自:https://blog.csdn.net/hjm4702192/article/details/80518856 本文围绕以下几点进行阐述 1.为什么使用redis2.使用redis有什么缺点 ...
随机推荐
- Golang omitempty 的用法
原文链接:https://blog.csdn.net/skh2015java/article/details/90720692omitempty作用是在json数据结构转换时,当该字段的值为该字段类型 ...
- neutron-server Connection pool is full, discarding connection 连接池过满
参考链接:https://zhiliao.h3c.com/Theme/details/48291 问题: -- ::33.235 WARNING requests.packages.urllib3.c ...
- seo排名顾问不仅仅是关键词排名
http://www.wocaoseo.com/thread-246-1-1.html SEO顾问是什么,应该做什么工作呢,是不是主要做关键词的优化推广呢?做seo顾问入门的人,或者想聘请seo顾问的 ...
- 这么高颜值的Kubernetes管理工具Lens,难道还不能C位出道吗
1 前言 欢迎访问南瓜慢说 www.pkslow.com获取更多精彩文章! Docker & Kubernetes相关文章:容器技术 一直使用官方的Kubernetes Dashboard来管 ...
- Promise、Generator,Async/await
我们知道JavaScript是单线程语言,如果没有异步编程非得卡死. 以前,异步编程的方法有下面四种 回调函数 事件监听 发布/订阅 Promise对象 现在据说异步编程终极解决方案是——async/ ...
- 自定义吐司以及Toast的各种用法,详解。教你学会使用各种各样的Toast
package com.david_Custoast; import com.david_Custoast.R; import android.app.Activity; import android ...
- 喵的Unity游戏开发之路 - 互动环境(有影响的运动)
如图片.视频或代码格式等显示异常,请查看原文: https://mp.weixin.qq.com/s/Sv0FOxZCAHHUQPjT8rUeNw 很多童鞋没有系统的Unity3D游戏开发基础,也不知 ...
- 编程体系结构(02):Java异常体系
本文源码:GitHub·点这里 || GitEE·点这里 一.异常简介 优秀的程序代码,都在追求高效,安全,和低错误率,但是程序中的异常是无法避免的,降低异常出现的频率是关键,异常出现如何处理是另一个 ...
- 超详细,Windows系统搭建Flink官方练习环境
如何快速的投入到Flink的学习当中,很多人在搭建环境过程中浪费了太多的时间.一套一劳永逸的本机Flink开发环境可以让我们快速的投入到Flink的学习中去,将精力用在Flink的原理,实战.这也对于 ...
- Spring security OAuth2.0认证授权学习第二天(基础概念-授权的数据模型)
如何进行授权即如何对用户访问资源进行控制,首先需要学习授权相关的数据模型. 授权可简单理解为Who对What(which)进行How操作,包括如下: Who,即主体(Subject),主体一般是指用户 ...