当前位置: 代码网 > it编程>编程语言>Java > 解决Long类型后端到前端精度丢失问题

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

2025年01月22日 Java 我要评论
long类型后端到前端精度丢失问题在开发中,后端经常需要处理一些大数值的 long 类型数据(id等)。但当这些数据通过接口传递到前端时,可能会出现精度丢失的问题。原因:javascript 的 nu

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,就能在全局范围内应用此配置,使得后端传递到前端的数据在大数值时也能准确无误。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com