如何处理long类型精度丢失问题

前言

由于项目原架构使用的是Vue2、Element-UI开发的前端,现在想集成Flowable工作流引擎,但公司采购的源码采用的是Vue3、TypeScriptElement-Plus,所以只能改造成Vue2,然后再使用

我的问题

主键使用的是雪花算法,长度有19位,前端接收到的id值会被四舍五入,导致数据无法正常被操作

这里分享两组值,分别是数据库存储的id和前端接收到的id值

  • 第一组值

数据库id值:1724983175923302401

前端id值:1724983175923302401

  • 第二组值

数据库id值:1724983439078129665

前端id值:1724983439078129700

从以上结果可以看出,数据被四舍五入了

问题分析

Number精度是16位(雪花ID是19位的),所以JS的Number数据类型导致的精度丢失。

解决方案

主要解决思路,还是把Long类型转换为String再传输,以下给出几种解决方案,主要针对不同应用场景

方案一(单个注解)

此方案适用于项目中有及个别字段需要处理,可以采用此种方案,如果项目中id全是雪花算法,此方案不推荐

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

方案二(全局配置)

Long类型的对象将会使用自定义的LongToStringSerializer进行序列化,将Long类型转换为字符串,从而避免在前端丢失精度的问题。

请确保你已经引入了正确的Jackson库,并且使用了相应的导入语句。

  1. 创建LongToStringSerializer
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;

public class LongToStringSerializer extends JsonSerializer<Long> {
    @Override
    public void serialize(Long value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeString(value.toString());
    }
}

2. 创建JacksonConfig

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;

import java.text.SimpleDateFormat;
import java.util.TimeZone;

@Configuration
public class JacksonConfig {

    @Bean
    public MappingJackson2HttpMessageConverter jackson2HttpMessageConverter() {
        final Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.serializationInclusion(JsonInclude.Include.NON_NULL);
        final ObjectMapper objectMapper = builder.build();
        SimpleModule simpleModule = new SimpleModule();
        // Long 转为 String 防止 js 丢失精度
        simpleModule.addSerializer(Long.class, new LongToStringSerializer());
        objectMapper.registerModule(simpleModule);
        // 忽略 transient 关键词属性
        objectMapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true);
        // 时区设置
        objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        return new MappingJackson2HttpMessageConverter(objectMapper);
    }
}

重启项目后,再查看前端id值,发现id值正常

- - - - - 本页内容已结束,喜欢请分享 - - - - -

感谢您的来访,获取更多精彩文章请收藏本站。

© 版权声明
THE END
喜欢就支持一下吧
点赞931 分享
评论 抢沙发
头像
你这么聪明,说什么都对!
提交
头像

昵称

夸夸
夸夸
还有吗!没看够!
取消
昵称表情代码图片

    暂无评论内容