java重写了WebMvcConfigurer的beforeBodyWrite方法后导致@JsonSerialize等失效
最近在做一个Spring Boot项目的时候需要重写WebMvcConfigurer的beforeBodyWrite方法,想要对响应体数据进行一定的加密操作,在自己调试接口并测试时无任何问题,等到和前端联调的时候,却出现了后台传过去的Long类型数据精度丢失的问题。
这里简单说下为什么会出现long数据精度丢失的情况:这主要是因为Java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值),导致Id最后几位直接变成了0,所以导致精度丢失。这也是为什么自己用类似于postman之类的工具调试接口时,并无任何不妥,但是一旦与前端联调,就会经常出现数据不存在的情况。
正常情况下,针对精度丢失最常用的也是最简单的方法,就是在后端给前端传值的时候,将long类型的数据转换成String,前端拿到的是一个string字符串,这样就不会出现问题,如下:
@JsonSerialize(using = LongJsonSerializer.class)
@JsonDeserialize(using = LongJsonDeserializer.class)
private Long id;
正常情况下这样处理是没有任何问题的,但是,在我重写了WebMvcConfigurer的beforeBodyWrite方法后,却出问题了:这里的注解@JsonSerialize和@JsonDeserialize全部失效了!为了搞清这个问题,我也在网上查了很多的资料,后来才发现产生这个问题的原因是因为 beforeBodyWrite
方法允许你在控制器方法执行之后但在响应体写入之前修改响应体,当你修改响应体时,Spring Boot 默认不再使用 Jackson 的序列化机制,因此这里所加的 注解就不会生效。
所以回到了最初的问题:处理long数据精度丢失的问题。
解决办法
这个问题后来找了一下,没发现有更好的处理办法,只有自己写了一段代码,手动的去将返回数据里的long值转换成String,如下:
public static void convertLongToString(JSONObject jsonObject) {
for (String key : jsonObject.keySet()) {
Object value = jsonObject.get(key);
// 检查是否为 Long 类型
if (value instanceof Long) {
// 将 Long 类型的值转换为 String 并更新 JSONObject
jsonObject.put(key,String.valueOf(value));
} else if (value instanceof JSONObject) {
// 如果是嵌套的 JSONObject,递归处理
convertLongToString((JSONObject) value);
}
}
}
当然,还有更直接更方便的处理办法:就是直接将返回对象里面的Long类型数据,全部修改成String类型,然后在接口返回处做一下类型转换,手动set一下值即可,唯一的缺点就是如果值多的话,每个值都要set一下就比较费事,而且万一哪个值忘记set了,拿到的就会是一个空值。
如果还有更好的处理方法,欢迎一起交流~
更多推荐
所有评论(0)