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了,拿到的就会是一个空值。

如果还有更好的处理方法,欢迎一起交流~

  • 8
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值