js long类型精度丢失_前端Long类型数据发生精度丢失问题

问题

用户在使用thub产品时发现展示的执行结果中,Long类型数据发生精度丢失问题。

实际值: 588208228525821697

前端显示 588208228525821700

排查发现后端返回数据数据是正确的,在前端显示出错了。

原因

参考文章 https://blog.csdn.net/u010028869/article/details/86563382

js使用双精度存储方式,因此对超长的整数值会丢失精度。

解决办法

后端对执行结果进行序列化,以格式化的字符串方式传输,字符串不存在精度问题 (需要改造数据格式,成本高)。

后端增加converter,在序列化的时候将long类型数据转成String (但是会对http接口产生全局影响)。(ToStringSerializer也可自定义实现) FastJsonConfig fastJsonConfig = new FastJsonConfig();

SerializeConfig serializeConfig = SerializeConfig.globalInstance;

serializeConfig.put(BigInteger.class, ToStringSerializer.instance);

serializeConfig.put(Long.class, ToStringSerializer.instance);

serializeConfig.put(Long.TYPE, ToStringSerializer.instance);

fastJsonConfig.setSerializeConfig(serializeConfig);

fastConverter.setFastJsonConfig(fastJsonConfig);

converters.add(fastConverter);​

自定义序列化方式,将超出表示范围的整数值在服务端存储时转为String (db存储会丢失真正数据类型)。 public class ThubLongSerializer implements ObjectSerializer {

public static ThubLongSerializer instance = new ThubLongSerializer();

@Override

public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features)

throws IOException {

SerializeWriter out = serializer.out;

if (object == null) {

out.writeNull();

return;

}

if (object instanceof Long) {

Long value = (Long)object;

if (value <= 9007199254740991L && value >= -9007199254740991L) {

out.writeLong(value);

if (out.isEnabled(SerializerFeature.WriteClassName) //

&& value <= Integer.MAX_VALUE && value >= Integer.MIN_VALUE //

&& fieldType != Long.class

&& fieldType != long.class) {

out.write('L');

}

return;

}

}

String strVal = object.toString();

out.writeString(strVal);

}

}

// 调用方式

SerializeConfig serializeConfig = new SerializeConfig();

serializeConfig.put(BigInteger.class, ThubLongSerializer.instance);

serializeConfig.put(Long.class, ThubLongSerializer.instance);

serializeConfig.put(Long.TYPE, ThubLongSerializer.instance);

String responseStr = JSONObject.toJSONString(record.getResponse(), serializeConfig,

SerializerFeature.WriteMapNullValue);

返回前端时特殊处理(遍历对象进行修改,实现比较复杂。继承并修改DefaultJSONParser类实现反序列化-麻烦,放弃)

效果

public static void main(String[] args) {

JSONObject jsonObject = new JSONObject();

jsonObject.put("test", 600008228525821697L);

SerializeConfig serializeConfig = new SerializeConfig();

serializeConfig.put(BigInteger.class, ThubLongSerializer.instance);

serializeConfig.put(Long.class, ThubLongSerializer.instance);

serializeConfig.put(Long.TYPE, ThubLongSerializer.instance);

String responseStr = JSONObject.toJSONString(jsonObject, serializeConfig,

SerializerFeature.WriteMapNullValue);

System.out.println(responseStr);

responseStr = JSONObject.toJSONString(jsonObject,

SerializerFeature.WriteMapNullValue);

System.out.println(responseStr);

}

{"test":"600008228525821697"}

{"test":600008228525821697}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值