IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

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

    满心记发表于 2023-11-16 06:17:15
    love 0

    前言

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

    我的问题

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

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

    数据库id值:1724983175923302401
    前端id值:1724983175923302401

    数据库id值:1724983439078129665
    前端id值:1724983439078129700

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

    问题分析

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

    解决方案

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

    方案一(单个注解)

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

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

    方案二(全局配置)

    Long类型的对象将会使用自定义的LongToStringSerializer进行序列化,将Long类型转换为字符串,从而避免在前端丢失精度的问题。
    请确保你已经引入了正确的Jackson库,并且使用了相应的导入语句。

    1. 创建LongToStringSerializer类
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      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类
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      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值正常



沪ICP备19023445号-2号
友情链接