解决Long类型后端到前端精度丢失问题

 更新时间:2025年01月21日 15:19:32   作者:qq_44199605  
文章讨论了后端Long类型数据通过JSON传递到前端时可能出现的精度丢失问题,原因在于JavaScript的Number类型精度限制,提出了两种解决方案:将Long类型序列化为String类型,或者配置全局的ObjectMapper使用ToStringSerializer,通过自定义JacksonConfig类

Long类型后端到前端精度丢失问题

在开发中,后端经常需要处理一些大数值的 Long 类型数据(id等)。但当这些数据通过接口传递到前端时,可能会出现精度丢失的问题。

原因:

JavaScript 的 Number 类型遵循 IEEE 754 双精度浮点数标准,只能精确表示范围在 -(2^53 - 1)2^53 - 1 之间的整数(约等于 -90071992547409919007199254740991)。

这意味着,任何超过这个范围的整数在 JavaScript 中都无法精确表示。

例如:

console.log(9007199254740991);    // 输出:9007199254740991(准确)
console.log(9007199254740992);    // 输出:9007199254740992(准确)
console.log(9007199254740993);    // 输出:9007199254740992(精度丢失)

在后端(例如 Java)中,Long 类型的范围是 -2^632^63 - 1,即 -92233720368547758089223372036854775807

这种数值在 Java 中可以被精确表示,但当通过 JSON 传递到前端的 JavaScript 环境时,由于 JavaScript 数字精度限制,往往会出现 精度丢失 的问题。

典型场景

当后端返回一个 ID 值 1234567890123456789,前端可能会收到 1234567890123456000,这样就导致了数据的错误。

解决方案

方案一:后端将 Long 类型序列化为 String 类型

一种简单有效的解决方案是,将后端的 Long 类型值序列化为 String,这样前端会将其当作字符串处理,从而避免了精度丢失的问题。下面是具体的实现方法。

1. 使用@JsonSerialize注解单独处理字段

如果只是需要处理某个特定字段(例如 id),可以在字段上添加 @JsonSerialize 注解,指定 Jackson 使用 ToStringSerializer 序列化器。

import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;

public class PassengerQueryResp {

    @JsonSerialize(using = ToStringSerializer.class)
    private Long id;

    private Long memberId;
    private String name;
    private String idCard;

    // Getter 和 Setter
}

配置了这个 ObjectMapper 之后,所有的 Long 类型字段在序列化时都会被转换为字符串格式,不再需要逐个字段添加注解。

2. 配置全局的ObjectMapper设置

如果需要对所有 Long 类型的字段进行字符串处理,可以在 Spring Boot 的配置类中定义一个全局 ObjectMapper Bean,使用 SimpleModule 注册 ToStringSerializer,这会对所有 Long 类型字段生效。

@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        objectMapper.registerModule(simpleModule);
        return objectMapper;
    }
}

配置类的作用详解

JacksonConfig 类中,通过以下代码将 Long 类型序列化为 String

SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
objectMapper.registerModule(simpleModule);

具体工作原理

1.Spring Boot 自动配置 ObjectMapper

  • Spring Boot 自带 Jackson 作为默认的 JSON 处理库,并在后台自动配置了 ObjectMapper
  • 当你在项目中引入 Jackson 时,Spring Boot 会自动加载一个全局共享的 ObjectMapper 实例,用于所有 JSON 序列化和反序列化操作。

2.控制器的自动 JSON 转换

  • 在 Spring MVC 中,控制器(@RestController@Controller)中的方法返回值会被自动转换为 JSON 格式,这个转换由 Spring Boot 的 ObjectMapper 处理。
  • 例如:
@RestController
public class UserController {
    @GetMapping("/user")
    public User getUser() {
        return new User(123456789012345L, "Alice");
    }
}
  • User 对象被返回时,Spring MVC 会自动使用 ObjectMapper 将其序列化为 JSON 响应发送给客户端。
  • 如果你配置了 JacksonConfig 类,Spring 会使用你配置的 ObjectMapper,因此所有 Long 类型字段会自动以字符串形式输出,避免精度丢失。

3.自定义 ObjectMapper 配置的全局效果

通过自定义 JacksonConfig,实际上是让 Spring Boot 使用你定义的 ObjectMapper Bean 作为全局配置。

Spring Boot 会自动检测应用中的 ObjectMapper Bean,并将其用于所有 JSON 序列化和反序列化操作,这包括:

  • @RestController 返回的对象。
  • @RequestBody@ResponseBody 注解处理的 JSON 请求和响应。
  • 其他 Spring Boot 内部或第三方库需要 JSON 处理的地方。

总结

在后端开发中处理 Long 类型数据时,注意 JavaScript 的精度限制十分重要。

通过配置 Jackson 的 ObjectMapper,可以让所有 Long 类型字段序列化为字符串,从而避免精度丢失的问题。

Spring Boot 的自动化配置特性让我们无需手动调用 ObjectMapper,就能在全局范围内应用此配置,使得后端传递到前端的数据在大数值时也能准确无误。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 关于maven下载慢的问题

    关于maven下载慢的问题

    这篇文章主要介绍了关于maven下载慢的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • Spring单例类加载多例属性问题实例解析

    Spring单例类加载多例属性问题实例解析

    本文给大家介绍Spring单例类加载多例属性问题实例解析,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2026-03-03
  • Java跨库事务如何实现保证

    Java跨库事务如何实现保证

    这段文章详细介绍了Java中实现跨库事务管理的方法,包括使用XA协议、Spring的JTA事务管理器和第三方解决方案如Seata,文章通过具体步骤和配置示例,解释了如何在Java应用中实现高效、可靠的分布式事务管理,适用于不同场景和需求
    2026-05-05
  • Javaweb resin4如何配置端口虚拟目录

    Javaweb resin4如何配置端口虚拟目录

    这篇文章主要介绍了Javaweb resin4如何配置端口虚拟目录,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • 使用MDC实现日志链路跟踪

    使用MDC实现日志链路跟踪

    这篇文章主要介绍了使用MDC实现日志链路跟踪,在微服务环境中,我们经常使用Skywalking、CAT等去实现整体请求链路的追踪,但是这个整体运维成本高,架构复杂,我们来使用MDC通过Log来实现一个轻量级的会话事务跟踪功能,下面就来看看具体的过程吧,需要的朋友可以参考一下
    2022-01-01
  • fastJson泛型如何转换的实现

    fastJson泛型如何转换的实现

    这篇文章主要介绍了fastJson泛型如何转换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • 基于Spring Cloud Gateway实现灰度发布的具体配置示例

    基于Spring Cloud Gateway实现灰度发布的具体配置示例

    这篇文章主要介绍了如何基于 Spring Cloud Gateway 实现灰度发布,核心思路是通过定义路由规则,将特定流量导向新版本服务,下面我用一个表格汇总主要策略,然后提供具体配置示例和关键说明,需要的朋友可以参考下
    2025-10-10
  • Java5 枚举类详解及实例代码

    Java5 枚举类详解及实例代码

    这篇文章主要介绍了Java5 枚举类详解及实例代码的相关资料,枚举类是java5 新类型,全部都是类型安全的形式表示,需要的朋友可以参考下
    2016-12-12
  • java编程实现根据EXCEL列名求其索引的方法

    java编程实现根据EXCEL列名求其索引的方法

    这篇文章主要介绍了java编程实现根据EXCEL列名求其索引的方法,涉及Java元素遍历与数学运算的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-11-11
  • spring中@Transactional 注解失效的原因及解决办法

    spring中@Transactional 注解失效的原因及解决办法

    面试中经常会被问到事务失效的场景有哪些,本文主要介绍了spring中@Transactional 注解失效的原因及解决办法,具有一定的参考价值,感兴趣的可以了解一下
    2024-06-06

最新评论