后端Long類型傳到前端精度丟失的正確解決方式


原因:前端js對Long類型支持的精度不夠,導致后端使用的Long傳到前端丟失精度,比如現在分布式id生成算法“雪花算法”在使用中就會出現問題。

解決方式:

1、后端的Long類型的id轉用String存儲,不推薦,失去了其Long類型本身的意義。

2、在Long類型字段上使用注解標明序列化方式,代碼量不大的情況可以考慮

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

3、實現WebMvcConfigurer接口,重寫configureMessageConverters方法

  @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter jackson2HttpMessageConverter =
                new MappingJackson2HttpMessageConverter();

        ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        objectMapper.registerModule(simpleModule);
        jackson2HttpMessageConverter.setObjectMapper(objectMapper);
        converters.add(jackson2HttpMessageConverter);
        converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
    }

但是這種方式需要開啟@EnableWebMvc注解。

開啟這個注解意味着springboot的mvc等自動配置失效,所以這個方式實際上也是不可取的。

類似的還有繼承WebMvcConfigurationSupport類,也會導致一些配置失效https://www.cnblogs.com/asker009/p/12752716.html

類似不可取的還有重寫HttpMessageConverters,這會覆蓋其他的類型轉換。

 

 
@Configuration
public class LongToJsonConfig {
    public LongToJsonConfig() {
    }
 
    @Bean
    public HttpMessageConverters customConverters() {
        MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        objectMapper.registerModule(simpleModule);
        jackson2HttpMessageConverter.setObjectMapper(objectMapper);
        return new HttpMessageConverters(new HttpMessageConverter[]{jackson2HttpMessageConverter});
    }
}

 

以上方式基本都不可取。

 

 

4、重新注冊ObjectMapper的Long類型序列化方式,推薦使用,暫時沒發現問題。

 

@Configuration
public class LongClassMessageConverter implements InitializingBean {

    @Resource
    ObjectMapper objectMapper;

    private SimpleModule getSimpleModule() {

        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        // 暫時放棄對小long的轉換,約定與前端交互數據時,大Long全部轉換成字符串
//        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        objectMapper.registerModule(simpleModule);
        return simpleModule;
    }


    @Override
    public void afterPropertiesSet() {
        SimpleModule simpleModule = getSimpleModule();
        objectMapper.registerModule(simpleModule);
    }
}

 

5、重新構建Jackson序列化方式,與第四點類似的解決方式,推薦使用。

@Configuration
public class JacksonConfig {
    /**
     * Jackson全局轉化long類型為String,解決jackson序列化時傳入前端Long類型缺失精度問題
     */
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        Jackson2ObjectMapperBuilderCustomizer cunstomizer = new Jackson2ObjectMapperBuilderCustomizer() {
            @Override
            public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
                jacksonObjectMapperBuilder.serializerByType(BigInteger.class, ToStringSerializer.instance);
                jacksonObjectMapperBuilder.serializerByType(Long.class, ToStringSerializer.instance);
//                jacksonObjectMapperBuilder.serializerByType(Long.TYPE, ToStringSerializer.instance);
            }
        };
        return cunstomizer;
    }
}

6、以上方式針對springboot默認的Jackson序列化,fastjson等其他json組件類似處理。

7、如果前端自身涉及到Long類型的計算,那么需要前端自己實現Long類型支持,參考:https://github.com/dcodeIO/long.js

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM