JavaScript 对大整数(超过 2^53 - 1)的精度丢失问题

遇到的问题:

后端返回的用户 ID 大概率是Long类型(64 位整数),而 JavaScript 的Number类型仅能精确表示 53 位整数,当 ID 超过2^53 - 1(即 9007199254740991)时,超出部分会被截断或舍入,导致前端接收的 ID 与后端不一致(精度丢失)。

下面提供 4 种解决方案,按「推荐优先级」排序,覆盖不同场景:

一、方案 1:后端改造(最优,从根源解决,无需前端大量修改)

核心思路:后端将Long类型的 ID 转为String类型返回给前端,前端接收字符串格式的 ID,不会存在精度丢失问题(字符串可完整保留所有数字)。

具体实现(后端):
  1. 方式 1:修改实体类,序列化时将Long转为String(推荐,全局 / 局部适配)若使用Jackson序列化(Spring Boot 默认),可通过注解@JsonFormat(shape = JsonFormat.Shape.STRING)@JsonProperty实现局部字段序列化,或配置全局序列化规则。
    import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import lombok.Data; @Data public class User { // 局部配置:将 Long 类型 ID 序列化为 String 类型返回 @JsonSerialize(using = ToStringSerializer.class) private Long id; // 后端存储仍为 Long,仅返回给前端时转为 String private String username; private String phone; private Integer status; }
  2. 方式 2:修改返回结果,手动将Long转为String若不想修改实体类,可在接口返回时,手动将id转为String(如使用Map或 DTO 封装返回结果)。
    // 示例:手动封装返回结果,将 id 转为 String @GetMapping("/user/admin/{id}") public CommonResponseVO<Map<String, Object>> getUserDetail(@PathVariable Long id) { User user = userService.getUserDetail(id); Map<String, Object> resultMap = new HashMap<>(); resultMap.put("id", user.getId().toString()); // Long 转 String resultMap.put("username", user.getUsername()); resultMap.put("phone", user.getPhone()); resultMap.put("status", user.getStatus()); resultMap.put("createTime", user.getCreateTime()); return CommonResponseVO.success(resultMap); }
前端处理:

无需额外修改逻辑,直接接收字符串格式的id即可(后续传递接口(如禁用 / 启用)时,字符串格式的id会被正常解析,后端可自动转换为Long类型)。

二、方案 2:前端使用BigInt类型处理大整数(纯前端改造,无需后端配合)

核心思路:将前端接收的数字类型 ID 转为BigInt类型BigInt是 JavaScript 专门用于表示大整数的类型,可精确表示任意长度的整数,无精度丢失问题。

具体实现(前端):
  1. 接收数据时,将id转为BigInt无论是表格数据还是详情数据,在赋值时将id转为BigInt(注意:BigInt不能与Number类型直接运算,需统一类型)。
    // 1. 分页查询用户时,处理 id 为 BigInt const handleQuery = async () => { try { loading.value = true; const params = { ...queryForm }; if (!params.status) delete params.status; if (!params.keyword) delete params.keyword; const res = await pageQueryUsers(params); // 遍历用户列表,将 id 转为 BigInt userList.value = (res.data.records || []).map(user => ({ ...user, id: BigInt(user.id) // 数字转 BigInt })); total.value = res.data.total || 0; } catch (error) { ElMessage.error(`用户查询失败:${error.message}`); } finally { loading.value = false; } }; // 2. 获取用户详情时,处理 id 为 BigInt const handleDetail = async (userId) => { try { detailLoading.value = true; detailDialogVisible.value = true; const res = await getUserDetail(userId); // 将详情中的 id 转为 BigInt userDetail.value = { ...res.data, id: BigInt(res.data.id) }; } catch (error) { ElMessage.error(`获取用户详情失败:${error.message}`); } finally { detailLoading.value = false; } };
  2. 传递接口参数时,将BigInt转为字符串(避免接口请求报错)BigInt类型直接传递到接口中会被序列化为"{ BigInt: "xxx" }",导致后端无法解析,因此传递时需转为字符串。
    // 禁用/启用用户时,将 BigInt 类型的 userId 转为字符串 const handleStatus = async (userId, currentStatus) => { const actionText = currentStatus === 1 ? '禁用' : '启用'; const targetStatus = currentStatus === 1 ? 0 : 1; try { await ElMessageBox.confirm( `确定要${actionText}该用户吗?`, '操作确认', { confirmButtonText: '确定', cancelButtonText: '取消', type: currentStatus === 1 ? 'warning' : 'info' } ); // BigInt 转字符串传递给接口 const res = await updateUserStatus(userId.toString(), targetStatus); if (res.result) { ElMessage.success(res.message || `${actionText}用户成功`); handleQuery(); } } catch (error) { if (error !== 'cancel') { ElMessage.error(`${actionText}用户失败:${error.message}`); } else { ElMessage.info(`已取消${actionText}操作`); } } };
  3. 模板中展示BigInt类型(直接展示即可,Vue 会自动转为字符串)
    <!-- 表格中展示 BigInt 类型的 id,无需额外处理 --> <el-table-column prop="id" label="用户ID" width="180"></el-table-column> <!-- 详情弹窗中展示 BigInt 类型的 id --> <el-descriptions-item label="用户ID">{{ userDetail.id || '-' }}</el-descriptions-item>
注意事项:
  • BigInt不支持JSON.stringify()直接序列化,若需存储或传递BigInt数据,需手动转为字符串;
  • BigInt不能与Number类型直接比较或运算,如需运算,需先将Number转为BigInt(如BigInt(10) + userId)。

三、方案 3:前端配置 Axios 响应拦截器,自动处理大整数 ID(全局适配,一劳永逸)

核心思路:在 Axios 响应拦截器中,遍历返回数据,将所有符合「大整数」特征的字段(如iduserId)自动转为StringBigInt,无需在每个接口中单独处理。

具体实现(前端,基于axios):
// src/utils/request.js import axios from 'axios'; import { useUserStore } from '@/store/modules/user'; const request = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL, timeout: 5000 }); // 请求拦截器(保留原有逻辑) request.interceptors.request.use( (config) => { const userStore = useUserStore(); if (userStore.accessToken) { config.headers['Authorization'] = `Bearer ${userStore.accessToken}`; } return config; }, (error) => Promise.reject(error) ); // 新增:工具函数 - 遍历对象/数组,处理大整数 ID const handleBigIntId = (data) => { if (typeof data !== 'object' || data === null) { return data; } // 数组处理 if (Array.isArray(data)) { return data.map(item => handleBigIntId(item)); } // 对象处理 const result = { ...data }; for (const key in result) { if (result.hasOwnProperty(key)) { const value = result[key]; // 1. 匹配 id 相关字段(id、userId、merchantId 等) // 2. 匹配数字类型,且超过 2^53 - 1 的大整数 if ( (key.toLowerCase() === 'id' || key.endsWith('Id')) && typeof value === 'number' && value > Number.MAX_SAFE_INTEGER ) { // 方案A:转为 String(推荐,兼容性更好) result[key] = value.toString(); // 方案B:转为 BigInt(需后续处理序列化问题) // result[key] = BigInt(value); } else if (typeof value === 'object' && value !== null) { // 递归处理嵌套对象 result[key] = handleBigIntId(value); } } } return result; }; // 响应拦截器(修改,添加大整数 ID 处理) request.interceptors.response.use( (response) => { const res = response.data; // 核心:处理返回数据中的大整数 ID const handledData = handleBigIntId(res); if (handledData.result === true) { return handledData; } else { return Promise.reject(new Error(handledData.message || '接口请求失败')); } }, (error) => Promise.reject(error) ); export default request;
优势:
  • 全局生效,所有接口返回的id相关字段都会被自动处理,无需在页面中单独修改;
  • 兼容性好,转为String后,后续操作(传递接口、展示、存储)均无问题;
  • 可扩展,可根据业务需求添加更多需要处理的字段(如orderIdgoodsId)。

四、方案 4:前后端约定 ID 长度限制(预防方案,适合新项目)

核心思路:后端限制Long类型 ID 的长度,确保其不超过2^53 - 1,这样 JavaScript 的Number类型可精确表示,无需额外处理。

具体说明:
  • 2^53 - 1对应的十进制数是 9007199254740991,约 9 万亿,对于大部分中小型项目,这个数值足够使用;
  • 后端可通过调整雪花算法(若使用)的机器位、时间位长度,限制 ID 不超过该数值;
  • 该方案仅适合新项目或数据量较小的项目,对于已有大 ID 的项目,无法回溯修改,仅能作为预防。

五、总结(推荐方案选择)

  1. 优先选择方案 1(后端改造):从根源解决问题,前端无需额外修改,兼容性最好,后续维护成本最低;
  2. 无法修改后端时,选择方案 3(Axios 全局拦截):一劳永逸,全局适配,无需在每个页面中单独处理大整数 ID;
  3. 仅个别接口需要处理时,选择方案 2(BigInt类型):灵活可控,适合局部场景;
  4. 新项目推荐方案 4(ID 长度限制):提前预防,避免后续出现精度丢失问题。

按以上方案处理后,前端接收的用户 ID 会完整保留精度,不会出现「后端正确、前端丢失」的问题,后续接口传递也能保持一致性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1149606.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

香江入梦·西湖共影:陈福善120周年大展在杭州启幕

​杭州&#xff0c;2026年元月&#xff0c;水光潋滟处&#xff0c;一场跨越香江与西湖的梦&#xff0c;悄然靠岸。由中心美术馆主办的《福善幻境——陈福善120周年大展》在杭州武林门古码头旁的杭州中心正式拉开帷幕。这位被誉为“香港水彩王”的艺术巨匠作品时隔近八年后再次大…

轻量高效!HY-MT1.5-1.8B模型在边缘设备的实时翻译应用

轻量高效&#xff01;HY-MT1.5-1.8B模型在边缘设备的实时翻译应用 在跨语言交流日益频繁的今天&#xff0c;传统云端翻译服务虽已成熟&#xff0c;却面临网络依赖、隐私泄露和延迟高等问题。尤其在医疗、法律、教育等对数据安全要求极高的场景中&#xff0c;离线部署的高精度翻…

如何实现专业级翻译?基于HY-MT1.5-7B的术语干预与格式保留实践

如何实现专业级翻译&#xff1f;基于HY-MT1.5-7B的术语干预与格式保留实践 随着全球化进程加速&#xff0c;跨语言内容处理需求激增。然而&#xff0c;通用机器翻译在专业领域常面临术语不一致、上下文缺失、格式错乱等问题&#xff0c;难以满足企业级应用对准确性与一致性的严…

使用Alpaca-LoRA微调类ChatGPT模型的实践指南

如何使用Alpaca-LoRA微调类似ChatGPT的模型 低秩自适应&#xff08;LoRA&#xff09;是一种用于微调模型的技术&#xff0c;相比之前的方法具有一些优势&#xff1a; 它更快且占用更少内存&#xff0c;这意味着可以在消费级硬件上运行。输出文件要小得多&#xff08;以兆字节计…

腾讯开源HY-MT1.5翻译大模型:小参数实现高质量翻译

腾讯开源HY-MT1.5翻译大模型&#xff1a;小参数实现高质量翻译 1. 引言&#xff1a;机器翻译的新范式——效率与质量的再平衡 在大模型“军备竞赛”愈演愈烈的今天&#xff0c;通用语言模型动辄千亿参数、数百GB显存需求&#xff0c;虽具备强大泛化能力&#xff0c;但在垂直任…

项目经理能力强不强,看他遇事的反应就知道了!

在项目管理中&#xff0c;突发状况是常态&#x1f649;&#xff0c;而且现在的项目变化的确也比以前更多——人更灵活不好管、风险更奇怪没见过、客户需求多更难说服等。 而遇到这些挑战时的第一反应&#xff0c;基本就能看出这个人适不适合做项目经理了。 1.遇事时&#xff…

告别CUDA报错:预置镜像一键运行AI分类器

告别CUDA报错&#xff1a;预置镜像一键运行AI分类器 引言 作为一名算法工程师&#xff0c;最头疼的莫过于换了新电脑后面对各种CUDA版本冲突、依赖库不兼容的问题。特别是当项目紧急需要恢复分类服务时&#xff0c;传统的手动配置环境往往需要耗费数小时甚至更长时间。这时候…

基于HY-MT1.5-7B大模型的多语言翻译实践|边缘部署与实时推理

基于HY-MT1.5-7B大模型的多语言翻译实践&#xff5c;边缘部署与实时推理 在跨语言交流日益频繁的今天&#xff0c;高质量、低延迟的机器翻译能力已成为智能应用的核心需求。腾讯开源的混元翻译大模型 HY-MT1.5-7B 以其卓越的多语言支持能力和对混合语种场景的精准处理&#xf…

腾讯混元翻译模型开源|HY-MT1.5实现多语言实时互译

腾讯混元翻译模型开源&#xff5c;HY-MT1.5实现多语言实时互译 1. 引言&#xff1a;大模型驱动下的翻译技术新范式 随着全球化进程加速&#xff0c;跨语言沟通需求激增。传统机器翻译系统在质量、延迟和部署成本之间难以平衡&#xff0c;尤其在边缘设备和实时场景中表现受限。…

三菱FX3U源码探秘:老司机带你玩转硬核PLC

三菱FX3U底层源码,PLSR源码&#xff0c;4路脉冲输出 总体功能和指令可能支持在RUN中下载程序&#xff0c;支持注释的写入和读取&#xff0c;支持脉冲输出与定位指令(包括PLSY /PWM/PLSR/PLSV/DRVI /DRVA 等指令)。 对于FX3U&#xff0c;支持波特率9600/19200/38400/57600/11520…

星哥带你玩飞牛NAS-16:飞牛云NAS换桌面,fndesk图标管理神器上线!

星哥带你玩飞牛NAS-16&#xff1a;飞牛云NAS换桌面&#xff0c;fndesk图标管理神器上线&#xff01; 引言 哈喽大家好&#xff0c;我是星哥&#xff0c;今天想跟大家聊聊一个特别实用的工具——fndesk&#xff0c;它能让你的飞牛云NAS桌面变得随心所欲。 飞牛云NAS虽然好用&…

如何在Windows上配置Windows防火墙,零基础入门到精通,收藏这篇就够了

打开Windows防火墙设置 通过控制面板&#xff1a;点击【开始】>【控制面板】>【系统和安全】>【Windows防火墙】。 通过搜索框&#xff1a;在任务栏的搜索框中输入“防火墙”&#xff0c;选择“Windows防火墙”。查看当前防火墙状态 在Windows防火墙设置界面&#xff…

支持术语干预与上下文翻译|HY-MT1.5大模型落地指南

支持术语干预与上下文翻译&#xff5c;HY-MT1.5大模型落地指南 随着多语言交流场景的不断扩展&#xff0c;传统云端翻译服务在隐私保护、网络依赖和响应延迟等方面的局限性日益凸显。特别是在企业级文档处理、边缘设备部署和少数民族语言支持等高敏感性或低资源环境中&#xf…

开发者福利:免费 .frii.site 子域名,一分钟申请即用

开发者福利&#xff1a;免费 .frii.site 子域名&#xff0c;一分钟申请即用前言在学习 Web 开发、部署项目、测试 API 或者搭建个人 Demo 时&#xff0c;一个可访问的域名往往是必需品。但很多同学不想为测试环境额外花钱&#xff0c;或者只是临时用一下&#xff0c;这时候免费…

三菱PLC功能块FB程序集(九个实用案例) - 清晰注释,成熟稳定应用,适用于伺服与变频器通讯...

三菱PLC功能块FB程序打包&#xff08;共九个&#xff09; 用的FB功能块写法&#xff0c;程序包括伺服FB和变频器通讯FB&#xff0c;编程方式非常清晰明了&#xff0c;程序都有注释、注释全面&#xff0c;包括三菱FX3U和Q系列plc。 可借鉴、可做模板&#xff0c;这些程序已经设…

电机控制工程师的日常调试中,最头疼的就是手里没示波器还要调过零点。今天咱们撸起袖子聊聊无位置BLDC的反电势检测,手把手造个能跑的模型出来

BLDC无位置反电势过零点检测模型先得明白反电势过零点的本质——当某相绕组反电势穿过零电位时&#xff0c;就是换相的最佳时机。但没位置传感器的情况下&#xff0c;咱得从悬空相端电压里扒拉出这个信号。硬件部分得保证电机中性点电压能被准确测量。这里有个取巧的方法&#…

从零部署多语言AI翻译|基于HY-MT1.5镜像的完整实践路径

从零部署多语言AI翻译&#xff5c;基于HY-MT1.5镜像的完整实践路径 在跨语言交流日益频繁的今天&#xff0c;高质量、低延迟的机器翻译能力已成为企业出海、政务服务、教育公平等场景的核心支撑。腾讯混元团队开源的 HY-MT1.5-1.8B 翻译模型&#xff0c;作为轻量级高性能翻译大…

vLLM加速HY-MT1.5-7B实战|实现低延迟高精度翻译服务

vLLM加速HY-MT1.5-7B实战&#xff5c;实现低延迟高精度翻译服务 随着全球化进程的不断推进&#xff0c;高质量、低延迟的多语言翻译服务已成为企业出海、跨文化交流和本地化运营的核心基础设施。腾讯开源的混元翻译大模型 1.5 版本&#xff08;HY-MT1.5&#xff09;在WMT25夺冠…

AI分类器商业应用:快速验证创意,成本可控1小时1块

AI分类器商业应用&#xff1a;快速验证创意&#xff0c;成本可控1小时1块 引言&#xff1a;创业者的AI验证困境 作为创业者&#xff0c;当你萌生一个"用AI做智能分类"的商业想法时&#xff0c;最头疼的问题往往是&#xff1a;这个需求真实存在吗&#xff1f;值得投…

AMAT 0100-01588 板

AMAT 0100-01588 板相关信息AMAT 0100-01588 板是 Applied Materials&#xff08;应用材料公司&#xff09;生产的设备部件&#xff0c;通常用于半导体制造设备中。以下是关于该板的一些关键信息&#xff1a;可能的用途该板可能用于设备控制、信号处理或电源管理模块。常见于 A…