一文详解JackSon配置信息
背景
1.1 问题
- Date返回日期格式(建议不使用Date,但老项目要兼容),带有T,如 2018-05-15T24:59:59:
- LocalDate返回日期对象为数组(框架中继承了 WebMvcConfigurationSupport);
- LocalDateTime时间转换失败等;
- 定义了日期类型,如LocalDate,前端对接时(post/get),如果传入日期字符串("2022-05-05"),会报String 转换为LocalDate失败;
- 返回long型数据,前端js存在精度问题,需做转换;
- 一些特殊对象要做业务特殊转换,如加解密等;
1.2 解决方案
- 针对特殊的具体对象,在对象上面使用注解,如:
@JsonSerialize(using= JsonDateSerializer.class)
private Date taskEndTime; @ApiModelProperty(value = "检查日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate checkDate;
- 重新实现WebMvcConfigurer接口,自定义JackSon配置。
- 继承 WebMvcConfigurationSupport类,自定义JackSon配置。
1.3 特别说明
- 方案1的模式,在对应变量上加上注解,是可以解决问题,但是严重编码重复,不优雅;
- 实现WebMvcConfigurer接口与继承WebMvcConfigurationSupport类,是Spring Boot提供开发者做统全局配置类的两种模式,注意两种模式的差异,详情查看后续章节介绍(两种不同的模式,使用不当时,就会出现配置不生效的情况);
自定义Jackson
JackSon配置说明

//在反序列化时忽略在 json 中存在但 Java 对象不存在的属性
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
false);
//在序列化时日期格式默认为 yyyy-MM-dd'T'HH:mm:ss.SSSZ ,比如如果一个类中有private Date date;这种日期属性,序列化后为:{"date" : 1413800730456},若不为true,则为{"date" : "2014-10-20T10:26:06.604+0000"}
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
//在序列化时忽略值为 null 的属性
mapper.setSerializationInclusion(Include.NON_NULL);
//忽略值为默认值的属性
mapper.setDefaultPropertyInclusion(Include.NON_DEFAULT);
// 美化输出
mapper.enable(SerializationFeature.INDENT_OUTPUT);
// 允许序列化空的POJO类
// (否则会抛出异常)
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
// 把java.util.Date, Calendar输出为数字(时间戳)
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// 在遇到未知属性的时候不抛出异常
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// 强制JSON 空字符串("")转换为null对象值:
mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
// 在JSON中允许C/C++ 样式的注释(非标准,默认禁用)
mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
// 允许没有引号的字段名(非标准)
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
// 允许单引号(非标准)
mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
// 强制转义非ASCII字符
mapper.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, true);
// 将内容包裹为一个JSON属性,属性名由@JsonRootName注解指定
mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
//序列化枚举是以toString()来输出,默认false,即默认以name()来输出
mapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING,true);
//序列化Map时对key进行排序操作,默认false
mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS,true);
//序列化char[]时以json数组输出,默认false
mapper.configure(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS,true);
//序列化BigDecimal时之间输出原始数字还是科学计数,默认false,即是否以toPlainString()科学计数方式来输出
mapper.configure(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS,true);
实现WebMvcConfigurer接口
编写LocalDateTime转换函数
/**
* java 8 LocalDateTime转换器
*
* @author wangling
*/
public class LocalDateTimeFormatter implements Formatter<LocalDateTime> {
private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); @Override
public LocalDateTime parse(String text, Locale locale) throws ParseException {
return LocalDateTime.parse(text, formatter);
} @Override
public String print(LocalDateTime object, Locale locale) {
return formatter.format(object);
}
}
编写LocalDate转换函数
/**
* java 8 localDate转换器
*
* @author wangling
*/
public class LocalDateFormatter implements Formatter<LocalDate> {
private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); @Override
public LocalDate parse(String text, Locale locale) throws ParseException {
return LocalDate.parse(text, formatter);
} @Override
public String print(LocalDate object, Locale locale) {
return formatter.format(object);
}
}
编写Jackson配置
/**
* 项目全局配置类
*
* @author wangling
* @date 2022/06/10
*/
@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer { @Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatterForFieldType(LocalDate.class, new LocalDateFormatter());
registry.addFormatterForFieldType(LocalDateTime.class, new LocalDateTimeFormatter());
} @Bean
@Primary
public ObjectMapper ObjectMapper() {
String dateTimeFormat = "yyyy-MM-dd HH:mm:ss";
String dateFormat = "yyyy-MM-dd";
String timeFormat = "HH:mm:ss";
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JavaTimeModule javaTimeModule = new JavaTimeModule();
// 序列化
javaTimeModule.addSerializer(
LocalDateTime.class,
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat)));
javaTimeModule.addSerializer(
LocalDate.class,
new LocalDateSerializer(DateTimeFormatter.ofPattern(dateFormat)));
javaTimeModule.addSerializer(
LocalTime.class,
new LocalTimeSerializer(DateTimeFormatter.ofPattern(timeFormat)));
javaTimeModule.addSerializer(
Date.class,
new DateSerializer(false, new SimpleDateFormat(dateTimeFormat))); // 反序列化
javaTimeModule.addDeserializer(
LocalDateTime.class,
new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(dateTimeFormat)));
javaTimeModule.addDeserializer(
LocalDate.class,
new LocalDateDeserializer(DateTimeFormatter.ofPattern(dateFormat)));
javaTimeModule.addDeserializer(
LocalTime.class,
new LocalTimeDeserializer(DateTimeFormatter.ofPattern(timeFormat)));
javaTimeModule.addDeserializer(Date.class, new DateDeserializers.DateDeserializer() {
@SneakyThrows
@Override
public Date deserialize(JsonParser jsonParser, DeserializationContext dc) {
String text = jsonParser.getText().trim();
SimpleDateFormat sdf = new SimpleDateFormat(dateTimeFormat);
return sdf.parse(text);
}
});
javaTimeModule.addSerializer(Long.class, ToStringSerializer.instance);
javaTimeModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
objectMapper.registerModule(javaTimeModule);
return objectMapper;
}
}
WebMvcConfigurationSupport类
编写Jackson配置

/**
* 项目全局配置类
*
* @author wangling
* @date 2022/06/10
*/
@Configuration
public class MvcInterceptorConfig extends WebMvcConfigurationSupport { @Override
protected void addFormatters(FormatterRegistry registry) {
// 用于get 全局格式化日期转换
registry.addFormatterForFieldType(LocalDate.class, new LocalDateFormatter());
registry.addFormatterForFieldType(LocalDateTime.class, new LocalDateTimeFormatter());
} @Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
// 代替框架默认的JackSon配置 用于post 全局格式化日期转换,long转字符串
MappingJackson2HttpMessageConverter jackson2HttpMessageConverter =
new MappingJackson2HttpMessageConverter();
jackson2HttpMessageConverter.setObjectMapper(ObjectMapper());
// 基于顺序,先执行自定义的
converters.add(0, jackson2HttpMessageConverter);
} private ObjectMapper ObjectMapper() {
String dateTimeFormat = "yyyy-MM-dd HH:mm:ss";
String dateFormat = "yyyy-MM-dd";
String timeFormat = "HH:mm:ss";
ObjectMapper objectMapper = new ObjectMapper();
//忽略空Bean转json的错误
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
//忽略 在json字符串中存在,但是在对象中不存在对应属性的情况,防止错误。
// 例如json数据中多出字段,而对象中没有此字段。如果设置true,抛出异常,因为字段不对应;false则忽略多出的字段,默认值为null,将其他字段反序列化成功
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JavaTimeModule javaTimeModule = new JavaTimeModule();
// 序列化
javaTimeModule.addSerializer(
LocalDateTime.class,
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat)));
javaTimeModule.addSerializer(
LocalDate.class,
new LocalDateSerializer(DateTimeFormatter.ofPattern(dateFormat)));
javaTimeModule.addSerializer(
LocalTime.class,
new LocalTimeSerializer(DateTimeFormatter.ofPattern(timeFormat)));
javaTimeModule.addSerializer(
Date.class,
new DateSerializer(false, new SimpleDateFormat(dateTimeFormat))); // 反序列化
javaTimeModule.addDeserializer(
LocalDateTime.class,
new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(dateTimeFormat)));
javaTimeModule.addDeserializer(
LocalDate.class,
new LocalDateDeserializer(DateTimeFormatter.ofPattern(dateFormat)));
javaTimeModule.addDeserializer(
LocalTime.class,
new LocalTimeDeserializer(DateTimeFormatter.ofPattern(timeFormat)));
javaTimeModule.addDeserializer(Date.class, new DateDeserializers.DateDeserializer() {
@SneakyThrows
@Override
public Date deserialize(JsonParser jsonParser, DeserializationContext dc) {
String text = jsonParser.getText().trim();
SimpleDateFormat sdf = new SimpleDateFormat(dateTimeFormat);
return sdf.parse(text);
}
});
javaTimeModule.addSerializer(Long.class, ToStringSerializer.instance);
javaTimeModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
objectMapper.registerModule(javaTimeModule);
return objectMapper;
}
}
WebMvcConfigurer与WebMvcConfigurationSupport相关知识点
基础知识点
WebMvcConfigurer 接口提供了很多方法让开发者来定制SpringMVC的配置。使用注意事项
- 实现WebMvcConfigurer: 不会覆盖WebMvcAutoConfiguration的配置
- 实现WebMvcConfigurer+注解@EnableWebMvc:会覆盖WebMvcAutoConfiguration的配置
- 继承WebMvcConfigurationSupport:会覆盖WebMvcAutoConfiguration的配置
- 继承DelegatingWebMvcConfiguration:会覆盖WebMvcAutoConfiguration的配置
推荐使用模式
- 非必要,最好避免WebMvcConfigurer,WebMvcConfigurationSupport在一个项目中同时使用;
- 出于安全性拦截配置,建议项目采用WebMvcConfigurer接口的方式做全局配置;
- 日期,时间等建议使用LocalDate,替换历史的Date数据类型;
一文详解JackSon配置信息的更多相关文章
- 一文详解Hexo+Github小白建站
作者:玩世不恭的Coder时间:2020-03-08说明:本文为原创文章,未经允许不可转载,转载前请联系作者 一文详解Hexo+Github小白建站 前言 GitHub是一个面向开源及私有软件项目的托 ...
- log4j.properties 详解与配置步骤(转)
找的文章,供参考使用 转自 log4j.properties 详解与配置步骤 一.log4j.properties 的使用详解 1.输出级别的种类 ERROR.WARN.INFO.DEBUGERROR ...
- C3P0连接池详解及配置
C3P0连接池详解及配置 本人使用的C3P0的jar包是:c3p0-0.9.1.jar <bean id = "dataSource" class = "com.m ...
- rsync的介绍及参数详解,配置步骤,工作模式介绍
rsync的介绍及参数详解,配置步骤,工作模式介绍 rsync是类unix系统下的数据镜像备份工具.它是快速增量备份.全量备份工具. Sync可以远程同步,支持本地复制,或者与其他SSH.rsync主 ...
- 磁盘分区对齐详解与配置 – Linux篇
在之前一篇<磁盘分区对齐详解与配置 – Windows篇>中,我介绍了磁盘分区对齐的作用和适用于MBR和GPT的两种磁盘类型的配置,以及Windows平台设置磁盘分区对齐的方法. 本文作为 ...
- tomcat启动nio,apr详解以及配置
tomcat启动nio,apr详解以及配置 前言 在正文开始之前,我们先在idea工具中看看启动的信息,顺便看下启动的基本信息 在这里插入图片描述可以看到信息有tomcat版本操作系统版本java版本 ...
- 一文详解 Linux 系统常用监控工一文详解 Linux 系统常用监控工具(top,htop,iotop,iftop)具(top,htop,iotop,iftop)
一文详解 Linux 系统常用监控工具(top,htop,iotop,iftop) 概 述 本文主要记录一下 Linux 系统上一些常用的系统监控工具,非常好用.正所谓磨刀不误砍柴工,花点时间 ...
- nginx的gzip模块详解以及配置
文章来源 运维公会:nginx的gzip模块详解以及配置 1.gzip模块作用 gzip这个模块无论在测试环境还是生产环境都是必须要开启,这个模块能高效的将页面的内容,无论是html或者css.j ...
- SpringBoot Profile使用详解及配置源码解析
在实践的过程中我们经常会遇到不同的环境需要不同配置文件的情况,如果每换一个环境重新修改配置文件或重新打包一次会比较麻烦,Spring Boot为此提供了Profile配置来解决此问题. Profile ...
随机推荐
- kali下安装docker
前期准备 物理机:win10 虚拟机:kali 2021 网络连接方式:桥接 一.简介 Vulhub: 是一个面向大众的开源漏洞靶场,无需docker知识,简单执行两条命令即可编译.运行一个完整的漏洞 ...
- 3.Docker容器学习之新手基础使用
原文地址: http://blog.weiyigeek.top/2019/5/2-docker%E5%AD%A6%E4%B9%A0%E4%B9%8B%E5%9F%BA%E7%A1%80%E4%BD%B ...
- Java语言学习day22--7月28日
###12多态概述 * A: 多态概述 多态是继封装.继承之后,面向对象的第三大特性. 现实事物经常会体现出多种形态,如学生,学生是人的一种,则一个具体的同学张三既是学生也是人,即出现两种形态. Ja ...
- python基础练习题(题目 输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数)
day10 --------------------------------------------------------------- 实例017:字符串构成 题目 输入一行字符,分别统计出其中英 ...
- opencv如何在jupyter notebook中显示图片
方法一: from matplotlib import pyplot as plt import numpy as np import cv2 img = cv2.imread('img.jpg') ...
- 【位运算】剑指offer 56. 数组中数字出现的次数
这是一系列位运算的题目,本文将由浅入深,先从最简单的问题开始: 问题1: 一个数组中只有一个数字出现过1次,其余数字都出现过两次,请找到那个只出现1次的数字.要求时间复杂度是 \(O(n)\),空间复 ...
- 渗透:winpcap
winpcap(windows packet capture)是windows平台下一个免费,公共的网络访问系统.开发winpcap这个项目的目的在于为win32应用程序提供访问网络底层的能力.它提供 ...
- 项目:PMBok
美国项目管理协会(PMI)资格认证之所以能在如此广的行业和地域范围内被迅速认可,首先是项目管理本身的重要性和实用性决定的,其次很大程度上是得益于该项认证体系本身的科学性.PMI早在七十年代末就率先提出 ...
- 【leetcode】239. 滑动窗口最大值
目录 题目 题解 三种解法 "单调队列"解法 新增.获取最大值 删除 代码 题目 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以 ...
- 以圆类 Circle 为基础设计球类 Sphere
学习内容:实验二以圆类 Circle 为基础设计球类 Sphere 代码示例: import java.util.Scanner; class Point{ private double x; pri ...