问题背景
JavaScript能处理的数据精度有限,长度一旦超过17位就会发生长度丢失。因此,id值在被序列化为JSON时经常会有后几位与原数据匹配不上的问题。
如图,页面通过get请求拿到用户数据
数据库中的数据
可以发现页面拿到的数据的id值和数据库中的id值最后两位不一致
为了解决该问题,可以将Long型转化为String
可利用jackson的ObjectMapper来实现
解决方法
ObjectMapper(对象转换器),是jackson中的一个类,它实现了java对象到JSON之间的转换(序列化、反序列化)。
当ObjectMapper中固有的序列化器(或反序列化器)不能满足我们的需求时,我们需要自定义一个对象转换器,即创建 ObjectMapper 的子类,为其添加新的序列化器,例如 (Long --> String) 的序列化器
实现步骤
1. 自定义对象转换器,添加序列化器(或反序列化器)
2. 将该对象转换器加入到 SpringMVC 的消息转换器队列中
1. 自定义对象转换器,添加序列化器(或反序列化器)
自定义的对象转换器即为ObjectMapper的子类,为其添加序列化器
/**
* 对象转换器 ObjectMapper:基于jackson将Java对象转为json(序列化),或者将json转为Java对象(反序列化)
*
* ObjectMapper中固有的序列化器(或反序列化器)可能不能满足我们的需求
* 因此需要创建 ObjectMapper 的子类,自定义新的序列化器,例如 Long --> String 的序列化器
*
*/
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_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 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(BigInteger.class, ToStringSerializer.instance)
.addSerializer(Long.class, ToStringSerializer.instance) // 实现 Long --> String 的序列化器
.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)));
// 对自定义的 simpleModule 进行注册
this.registerModule(simpleModule);
}
}
现在已经创建出了自定义的对象转换器,但还无法生效,需要对它进行相关配置
2. 将该对象转换器加入到 SpringMVC 的消息转换器队列中
在WebMVC配置类中,重写extendMessageConverters方法,将自定义的对象转换器加入到消息转换器队列中,使其生效
/**
* 扩展 Spring MVC 的消息转换器
*
* 将自定义的对象转换器 JacksonObjectMapper 加入到 SpringMVC 的消息转换器队列中
*
* @param converters
*/
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
log.info("扩展消息转换器......");
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
messageConverter.setObjectMapper(new JacksonObjectMapper());
converters.add(0, messageConverter);
}
再次测试结果如下
可以发现此时页面拿到的id值都已经变成了String,而且与数据库中的id值完全一致
如此,便解决了Long型长度丢失问题