前端Long类型精度丢失:后端处理策略

文章目录

    • 精度丢失的具体原因
    • 解决方法
      • [1. 使用 `@JsonSerialize` 和 `ToStringSerializer`](#1. 使用 @JsonSerializeToStringSerializer)
      • [2. 使用 `@JsonFormat` 注解](#2. 使用 @JsonFormat 注解)
      • [3. 全局配置解决方案](#3. 全局配置解决方案)
    • 结论

开发商城管理系统的品牌管理界面时,发现一个问题,接口返回品牌Id和页面展示的品牌Id不一致,如接口返回的是1816714744603811841,前端战胜的是1816714744603811800

这是因为在前端出现了数据精度丢失。

精度丢失的具体原因

JavaScript的Number类型用于表示浮点数,它遵循IEEE 754标准中的64位浮点数格式。这意味着它能够准确表示从(-2{53})到(2{53}-1)之间的所有整数。超出这个范围的整数值在转换为Number类型时可能会发生精度丢失,即原本不同的长整数会被转换成相同的浮点数值,从而导致数据失真。

解决方法

为了解决品牌ID在前后端传输过程中精度丢失的问题,可以采用以下几种解决方法:

1. 使用 @JsonSerializeToStringSerializer

在Java后端中,可以通过使用Jackson库的注解功能,将Long类型的字段在序列化为JSON时转换为String类型。这样,前端接收到的数据是字符串形式,避免了精度丢失的问题。

示例代码:

java 复制代码
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;

@Data
public class BrandVo {
    // 使用ToStringSerializer将Long类型的id字段转换为String类型
    @JsonSerialize(using = ToStringSerializer.class)
    private Long id;
    // 其他字段...
}

通过这种方式,我们可以确保后端返回的JSON中,Long类型的字段都以字符串的形式存在,前端可以直接将其作为字符串处理,无需担心精度问题。

2. 使用 @JsonFormat 注解

除了使用 ToStringSerializer,Jackson还提供了 @JsonFormat 注解,它允许指定字段的序列化格式。当将 shape 属性设置为 JsonFormat.Shape.STRING 时,Long类型的字段会被格式化为字符串。

示例代码:

java 复制代码
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;

@Data
public class BrandVo {
    // 使用@JsonFormat注解将Long类型的id字段格式化为String
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long id;
    // 其他字段...
}

这种方法同样可以确保Long类型的字段在序列化为JSON时以字符串形式出现,避免前端精度丢失的问题。

3. 全局配置解决方案

虽然使用注解可以在一定程度上解决问题,但对于大型项目,逐个字段添加注解不仅繁琐,还可能导致代码冗余和难以维护。因此,可以考虑使用全局配置的方式,一次性解决所有Long类型字段的序列化问题。

示例代码:

java 复制代码
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@Configuration
public class JacksonConfig {

    @Bean
    @Primary
    @ConditionalOnMissingBean(ObjectMapper.class)
    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        SimpleModule simpleModule = new SimpleModule();
        // 将Long类型序列化为String类型
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        objectMapper.registerModule(simpleModule);
        return objectMapper;
    }
}

在这个配置中,我们创建了一个自定义的ObjectMapper Bean,并注册了一个SimpleModule,该模块使用ToStringSerializer将Long类型序列化为String类型。这样,整个应用中所有Long类型的字段在序列化时都会自动转换为String类型。

结论

前端精度丢失问题是一个常见的挑战,但通过上述三种方法,我们可以有效地解决这个问题。在实际开发中,我们可以根据项目的具体情况和需求选择合适的方法。对于需要精确表示大数字的场景,将Long类型转换为String类型是一个简单而有效的解决方案。

相关推荐
无奈何杨几秒前
CoolGuard风控中新增移动距离和移动速度指标
前端·后端
掘金-我是哪吒6 分钟前
分布式微服务系统架构第157集:JavaPlus技术文档平台日更-Java多线程编程技巧
java·分布式·微服务·云原生·架构
恋猫de小郭8 分钟前
Google I/O Extended :2025 Flutter 的现状与未来
android·前端·flutter
江城开朗的豌豆12 分钟前
Vue-router方法大全:让页面跳转随心所欲!
前端·javascript·vue.js
飞翔的佩奇14 分钟前
Java项目:基于SSM框架实现的忘忧小区物业管理系统【ssm+B/S架构+源码+数据库+毕业论文+开题报告】
java·数据库·mysql·vue·毕业设计·ssm框架·小区物业管理系统
阿蒙Amon14 分钟前
C#扩展方法全解析:给现有类型插上翅膀的魔法
开发语言·c#
程序员爱钓鱼22 分钟前
Go语言泛型-泛型约束与实践
前端·后端·go
前端小巷子23 分钟前
web从输入网址到页面加载完成
前端·面试·浏览器
江城开朗的豌豆24 分钟前
Vue路由动态生成秘籍:让你的链接'活'起来!
前端·javascript·vue.js
晓得迷路了24 分钟前
栗子前端技术周刊第 88 期 - Apache ECharts 6.0 beta、Deno 2.4、Astro 5.11...
前端·javascript·echarts