js 丢失 Long 精度 解决方案

方法:传给前端时转成String

  • 单个
/**
 * ID
 */
@JsonSerialize(using = ToStringSerializer.class)
private Long id;

 

  • 全局(推荐使用) SpringBoot2

参考:

  1. SpringBoot全局配置long转String丢失精度的问题解决_java_脚本之家 (jb51.net)
  2. 版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。

    本文链接:http://www.miss168.net/detail/science/631252567581528064/0/844370244045639680
  3. 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
    本文链接:https://blog.csdn.net/qq_31424825/article/details/117809472

/**
 * WebMvc配置
 *
 * @author : JZDELD
 * @date : 2021/11/19 14:00
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {

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

        ObjectMapper objectMapper = new ObjectMapper();
        /**
         * 序列换成json时,将所有的long变成string
         * 因为js中得数字类型不能包含所有的java long值
         */
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        objectMapper.registerModule(simpleModule);

        /**
         * 2021/11/27
* 遇到一个问题,手动重写json转换后,前端请求参数中的多余字段,导致请求报错, * 重写前框架自带的方法是不报错的,那只有手动解决了
*/ objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); jackson2HttpMessageConverter.setObjectMapper(objectMapper); /** * 现在好多项目都用到了long型ID,如果不做处理,返回到前端的精度会丢失,为了解决这个方法, * 只能重写configureMessageConverters,很多人都遇到重写这个不生效的情况,都有分析原因, * 是因为有一个默认的消息转换器排在我们自定义的前面导致不生效,有的说加注解@EnableWebMvc, * 有的说定义一个Bean等等,知道原因后解决其实没那么复杂,我们只需要将自定义的消息转换器放到前边即可, * 下面是代码: */ // index 0 关键 核心就在这里,把它添加到首位还担心他不生效吗 converters.add(0, jackson2HttpMessageConverter); } }

 

  • 更好的全局配置

使用自定义的 JsonSerializer

/**
 * 如果 long 大于 int 最大值 转成字符串
 *
 * @author JZDELD
 * @date 2021/11/29 14:06
 */
public class LongToLongOrStringSerializer extends JsonSerializer<Long> {
    /**
     * Singleton instance to use.
     */
    public final static LongToLongOrStringSerializer instance = new LongToLongOrStringSerializer();

    /**
     * js的number类型有个最大值(安全值)。即2的53次方,为9007199254740992
     */
    public final static Long JS_LONG_MAX = 0x20000000000000L;
    /**
     * 最大的15位数 999,999,999,999,999
     */
    public final static Long LONG_MAX_DIGITS_15 = 0x38d7ea4c67fffL;

    @Override
    public void serialize(Long value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if (value == null) {
            return;
        }
        if (value > JS_LONG_MAX) {
            gen.writeString(value.toString());
        } else {
            gen.writeNumber(value);
        }
    }
}

WebConfig

/**
 * WebMvc配置
 *
 * @author : JZDELD
 * @date : 2018/12/13 16:49
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        for (HttpMessageConverter<?> converter : converters) {
            // 保留了yml中的jackson配置
            if (converter instanceof MappingJackson2HttpMessageConverter) {
                MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = (MappingJackson2HttpMessageConverter) converter;
                // MappingJackson2HttpMessageConverter 加上 Long 转 String
                updateMappingJackson2HttpMessageConverter(jackson2HttpMessageConverter);
                break;
            }
        }
    }

    /**
     * 给 MappingJackson2HttpMessageConverter 加点东西
     *
     * @param jackson2HttpMessageConverter
     */
    private void updateMappingJackson2HttpMessageConverter(MappingJackson2HttpMessageConverter jackson2HttpMessageConverter) {
        ObjectMapper objectMapper = jackson2HttpMessageConverter.getObjectMapper();

        /**
         * 序列换成json时,将所有的long变成string
         * 因为js中得数字类型不能包含所有的java long值
         */
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Long.class, LongToLongOrStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, LongToLongOrStringSerializer.instance);
        objectMapper.registerModule(simpleModule);

        /**
         * 遇到一个问题,手动重写json转换后,前端请求参数中的多余字段,导致请求报错,
         * 重写前框架自带的方法是不报错的,那只有手动解决了
         */
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        jackson2HttpMessageConverter.setObjectMapper(objectMapper);
    }
}    

 

posted @ 2021-11-19 14:27  JZDELD  阅读(486)  评论(0)    收藏  举报