解决JS处理api返回number字段精度丢失问题

本文探讨前端使用axios调用第三方接口时,因ID值超出JavaScript number范围导致精度丢失的问题。提供两种解决方案:转换为字符串或自定义JSON解析。

前端在ajax方式调用第三方接口时出现了一个诡异的问题,同一个接口url通过axios访问接口获取到的数据与浏览器访问的数据id不一致,如下图所示:

通过浏览器访问的数据id

 

axios ajax访问到的数据

axios ajax response数据 

可以很明显看到这个长整数的最后一位精度损失了,马上联想到应该是数字类型的长度过长,超出了js number类型处理的长度。 

查资料验证了一下对问题的判断,确认了问题出在了对接口响应结果的JSON.parse解析阶段,JSON解析时由于JS在处理id字段对应为number类型时,超出了JS的number类型最大2的53次方范围,因此超出的精度被舍弃导致。

根据问题分析的原因,由于使用axios发起的接口请求,前端可采取的解决方案主要有两种:

1)在进行JSON.parse之前,将返回字符串中的长整型替换为字符串类型;

let reqObj = {
    url: `${URL.ADSERVICE_HOST}appapi/getAdspaceList`,
    method: 'get',
    params: query,
    transformResponse: [response => JSON.parse(response.replace(/("id":)(\d{0,})(,)/g, '$1'+'"'+'$2'+'"'+'$3'))]    //采用分组匹配,$1匹配"id":,$2匹配id值,$3匹配,
  }

axios(reqObj).then((response) => { 
	console.log(response.data)
 })

2)从JSON.parse入手,不使用原生的JSON解析,采用自定义的JSON解析方法。

 此种方式可参考:【解决方案】jison解决JS处理后台返回的Long型数据精度丢失_Kuroko's Development Notes-优快云博客

<think> 我们之前已经讨论过这个问题,但用户再次提问,需要确保回答完整且符合格式要求。 问题核心:Java后端返回Long类型ID,Vue前端JavaScript接收时精度丢失解决方案: 1. 后端将Long类型ID转为字符串返回(推荐) 2. 前端使用json-bigint等库解析JSON 3. 前端手动转换ID为字符串 注意:必须按照用户要求的格式输出,末尾附上相关问题。 </think> ### Java后端返回ID,Vue前端精度丢失解决方案 当Java后端返回Long类型ID(如雪花ID)时,Vue前端接收会出现精度丢失问题。这是因为Java的Long类型(64位)超出JavaScriptNumber类型安全范围(±2^53-1)。以下是完整解决方案: #### 一、后端处理方案(推荐) 1. **DTO字段序列化为字符串** ```java public class UserDTO { @JsonFormat(shape = JsonFormat.Shape.STRING) // Jackson注解 private Long id; // 其他字段... } ``` 2. **全局配置(Spring Boot)** ```java @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); ObjectMapper mapper = new ObjectMapper(); mapper.configOverride(Long.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING)); converter.setObjectMapper(mapper); converters.add(0, converter); } } ``` #### 二、前端处理方案 1. **使用json-bigint库** ```javascript // axios配置 import axios from 'axios'; import JSONbig from 'json-bigint'; const api = axios.create({ transformResponse: [data => { try { return JSONbig.parse(data); // 自动转换大数字为BigInt } catch (e) { return JSON.parse(data); } }] }); // 使用示例 api.get('/user').then(res => { console.log(String(res.data.id)); // 转为字符串使用 }); ``` 2. **响应拦截器转换** ```javascript axios.interceptors.response.use(response => { const convertId = (obj) => { if (obj && typeof obj === 'object') { Object.keys(obj).forEach(key => { if (key.toLowerCase().includes('id') && typeof obj[key] === 'number') { obj[key] = String(obj[key]); // 所有ID字段转为字符串 } }); } return obj; }; response.data = convertId(response.data); return response; }); ``` #### 三、混合方案 1. **BigInt前端处理** ```javascript // 获取数据后转换 api.get('/data').then(res => { const data = { ...res.data, id: BigInt(res.data.id).toString() // 转为字符串 }; }); ``` 2. **TS类型强制(Vue3+TS)** ```typescript interface User { id: string; // 强制定义为字符串类型 name: string; } ``` #### 四、注意事项 1. **精度丢失测试**:当ID > 9,007,199,254,740,991时必定丢失精度 2. **模板渲染**:Vue模板中直接使用 `{{ item.id }}` 需确保id是字符串 3. **数据库设计**:超过16位的ID建议使用字符串存储 > **推荐方案**:后端统一返回字符串ID + 前端axios拦截器二次保障
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值