您觉得本文档还缺少什么内容?可以自己补充~
为了统一参数格式和数据精度丢失等问题,本项目做了采用jackson进行全局的序列化和反序列化配置。
名词解释:
- 序列化:Controller层接口返回值 转成 json 格式的过程
- 反序列化:前端请求通过json格式提交参数到 Controller 层的过程
全局配置
在BaseConfig类配置了全局的ObjectMapper 实例, 并对objectMapper进行了自定义配置。 注意:配置全局ObjectMapper类后,会和yml配置文件中 spring.jackson.xxx 的配置产生冲突,所以请勿在yml中重复配置
@Bean
@Primary
@ConditionalOnClass(ObjectMapper.class)
@ConditionalOnMissingBean
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
objectMapper
// 设置当前位置
.setLocale(Locale.CHINA)
//去掉默认的时间戳格式
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
// 时区
.setTimeZone(TimeZone.getTimeZone(ZoneId.systemDefault()))
//Date参数日期格式
.setDateFormat(new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT, Locale.CHINA))
//该特性决定parser是否允许JSON字符串包含非引号控制字符(值小于32的ASCII字符,包含制表符和换行符)。 如果该属性关闭,则如果遇到这些字符,则会抛出异常。JSON标准说明书要求所有控制符必须使用引号,因此这是一个非标准的特性
.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true)
// 忽略不能转义的字符
.configure(JsonReadFeature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER.mappedFeature(), true)
//在使用spring boot + jpa/hibernate,如果实体字段上加有FetchType.LAZY,并使用jackson序列化为json串时,会遇到SerializationFeature.FAIL_ON_EMPTY_BEANS异常
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
//忽略未知字段
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
//单引号处理
.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
// 注册自定义模块
objectMapper.registerModule(new BcJacksonModule())
.registerModule(new SimpleModule().addDeserializer(RemoteData.class, RemoteDataDeserializer.INSTANCE))
.findAndRegisterModules();
}
序列化自定义配置项
Long -> String
1) 实现代码
public BcJacksonModule() {
this.addSerializer(Long.class, ToStringSerializer.instance);
this.addSerializer(Long.TYPE, ToStringSerializer.instance);
}
2)最终效果
Controller层接口返回参数中,Long类型的字段,会转成字符串。
{
"id": "29984253320102284"
}
3)解决问题: 解决前端获取到Long类型的字段后,精度丢失问题。 (更多信息自行百度&谷歌)
- BigInteger -> String 1) 实现代码
public BcJacksonModule() {
this.addSerializer(BigInteger.class, ToStringSerializer.instance);
}
2) 最终效果&解决问题:同上
- BigDecimal -> String 1) 实现代码
public BcJacksonModule() {
this.addSerializer(BigDecimal.class, ToStringSerializer.instance);
}
2) 最终效果&解决问题:同上
- Date -> String 1) 实现代码
public class BaseConfig {
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
objectMapper
//Date参数日期格式
.setDateFormat(new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT, Locale.CHINA))
// ...
}
}
2) 最终效果 Controller层接口返回参数中,Date类型的字段,会转成字符串。
{
"date": "yyyy-MM-dd HH:mm:ss" // 这里的格式由上面的 DEFAULT_DATE_TIME_FORMAT 决定
}
3)解决问题: 统一日期参数的统一格式
- LocalDateTime -> String 1) 实现代码
public BcJacksonModule() {
this.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
}
2) 最终效果 Controller层接口返回参数中,LocalDateTime类型的字段,会转成字符串。
{
"createTime": "yyyy-MM-dd HH:mm:ss"
}
3)解决问题: 同上
- LocalDate -> String 1) 实现代码
public BcJacksonModule() {
this.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
}
2) 最终效果 Controller层接口返回参数中,LocalDate类型的字段,会转成字符串。
{
"createTime": "yyyy-MM-dd"
}
3)解决问题: 同上
- LocalTime -> String 1) 实现代码
public BcJacksonModule() {
this.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
}
2) 最终效果 Controller层接口返回参数中,LocalTime类型的字段,会转成字符串。
{
"createTime": "HH:mm:ss"
}
3)解决问题: 同上
反序列化自定义配置项
- String -> Long
- Object -> BaseEnum
- String -> BaseEnum
String -> LocalDate, 支持前端传递格式:
yyyy-MM-dd
: 如:2021-11-11String -> LocalDateTime, 支持前端传递格式:
yyyy-MM-dd
: 如:2021-11-11yyyy/MM/dd
: 如:2021/11/11yyyy年MM月dd日
: 如:2021年11月11日yyyy-MM-dd HH:mm:ss
: 如:2021-11-11 11:11:11yyyy/MM/dd HH:mm:ss
: 如:2021/11/11 11:11:11yyyy年MM月dd日HH时mm分ss秒
: 如:2021年11月11日11时11分11秒String -> LocalTime 支持前端传递格式:
HH:mm:ss
- Object -> RemoteData
- String -> RemoteData 1) 实现代码:以上几点的实现代码均在 BcJacksonModule 类 2) 最终效果:按照上述序列化的 参数格式提交json参数,会自动将参数封装到入参对象中 3) 解决问题:实现参数格式统一化(序列化和反序列化格式统一),并且为了减少报错率,BaseEnum和RemoteData类型的参数,在传递时,既可以以字符串的格式传递,也可以以object的格式传递。如:
{
"sex": "M",// 格式1
"sex": {
"code": "M" // 格式2
}.
"createTime": "yyyy-MM-dd HH:mm:ss"
}