Long和Long类型集合前端精度丢失解决办法锦集以及自定义JSON序列化方法
source link: http://www.lzhpo.com/article/106
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Long
和List<Long>
前端精度丢失解决办法锦集以及自定义JSON序列化方法
因为JS解析整型的时候是有最大值的,Number.MAX_SAFE_INTEGER
常量表示在 JavaScript 中最大的安全整数(maxinum safe integer)(253 - 1)
Number.MAX_SAFE_INTEGER // 9007199254740991Math.pow(2, 53) - 1 // 9007199254740991
最大长度是16位数,超过了就解析不正常了,会丢失精度。
我后端是用的雪花算法生成的20位的唯一ID,我返回给前端的时候,例如:
我返回的是Long类型的,但是前端接收之后精度丢失,导致和我后端给的不一致,解决办法就是使用String类型的。
方法1 -后端传输JSON格式化为String类型的。
@JsonFormat(shape = JsonFormat.Shape.STRING)private Long aliyunOssFileId;
@JsonFormat(shape = JsonFormat.Shape.STRING)
作用就是将JSON数据的此字段格式化为字符串类型,保证前端超过16位不会出现精度丢失问题!
但是,如果有很多Long类型的话,要一个一个去改,也太累了,Spring MVC中默认是使用了Jackson的,可以通过重写转换器解决。
方法2-重写转换器(Jackson)
import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.module.SimpleModule;import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;import com.leyou.order.interceptor.LoginInterceptor;import com.leyou.order.properties.JwtProperties;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.http.converter.HttpMessageConverter;import org.springframework.http.converter.StringHttpMessageConverter;import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;import org.springframework.web.servlet.config.annotation.EnableWebMvc;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.math.BigInteger;import java.nio.charset.Charset;import java.util.ArrayList;import java.util.List;@Configuration@EnableWebMvcpublic class MvcConfig implements WebMvcConfigurer { /** * Long类型转String类型 * * 解决前端Long类型精度丢失问题(js解析只能解析到16位) * * @param converters * @author Zhaopo Liu */ @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)); }}
方法3-如果是FastJson的话
在Spring Boot中将Jackson替换为fastjson一般会有两种方式:
第一种:
@Configurationpublic class WebConfig extends WebMvcConfigurerAdapter { @Bean public HttpMessageConverters fastJsonHttpMessageConverter() { return new HttpMessageConverters(new FastJsonHttpMessageConverter()); }}
@Configurationpublic class WebConfig extends WebMvcConfigurerAdapter { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); FastJsonConfig fastJsonConfig = new FastJsonConfig(); fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat); fastConverter.setFastJsonConfig(fastJsonConfig); converters.add(fastConverter); }}
替换成fastjson之后,对于精度丢失问题,解决方法如下:
@EnableWebMvc@Configurationpublic class WebConfig extends WebMvcConfigurerAdapter { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); 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); }}
方法4-前端使用String类型来接收
aliyunOssFileId: ''
方法5-List<Long>
类型精度丢失问题
最好的方式就是,将List<Long>
改为List<String>
方式,这样子啥事没有,性能也高,但是我就是想多折腾:
1.数组转换为String显示(不推荐)
直接使用官方的即可:
@JsonSerialize(using = ToStringSerializer.class)private List<Long> roleIds;
前端显示的,这明显需要前端特殊处理,个人不太喜欢这样子:
{ "roleIds": "[1333010224414613506, 1333010224481722369]"}
2.自定义序列化方式转换为String数组(推荐)
自定义一个JSON序列化方式:
package com.lzhpo.common.serializer;import com.fasterxml.jackson.core.JsonGenerator;import com.fasterxml.jackson.databind.JsonSerializer;import com.fasterxml.jackson.databind.SerializerProvider;import com.lzhpo.common.enums.ResultStatus;import com.lzhpo.common.exception.CustomException;import lombok.extern.slf4j.Slf4j;import java.io.IOException;import java.util.List;import java.util.Optional;/** * {@code List<Long>} to {@code List<String>} * * <pre> * e.g: * - @JsonSerialize(using = ListLongToStringArrayJsonSerializer.class) * private List<Long> roleIds; * </pre> * * @author Zhaopo Liu */@Slf4jpublic class ListLongToStringArrayJsonSerializer extends JsonSerializer<List<Long>> { @Override public void serialize(List<Long> values, JsonGenerator gen, SerializerProvider serializers) throws IOException { log.info("List<Long> to String[] created by values:{}", values); try { gen.writeArray( Optional.ofNullable(values.isEmpty() ? null : values) .map(list -> list.stream().map(String::valueOf).toArray(String[]::new)) .orElseGet(() -> new String[0]), 0, values.size()); } catch (IOException e) { throw new CustomException(ResultStatus.FAIL, "Convert JSON string array error:" + e.getMessage()); } }}
使用方式:
@JsonSerialize(using = LongToJsonSerializer.class)private List<Long> roleIds;
{ "roleIds": [ "1333010224414613506", "1333010224481722369" ]}
Recommend
-
25
一、泛型集合List<T>排序 经sort方法之后,采用了升序的方式进行排列的。 List<int> list = new List<int>() { 2, 4, 1, 3, 5, -2, 0, 10 }; Console.Write("排序前...")...
-
7
更新丢失、写偏、幻读:数据库事务从快照隔离到可序列化(番外) 作者:青菜年糕汤 更新丢失、写偏、幻读:数据库事务从快照隔离到可序列化(一,
-
8
更新丢失、写偏、幻读:数据库事务从快照隔离到可序列化(三) 作者:青菜年糕汤 更新丢失、写偏、幻读:数据库事务从快照隔离到可序列化(一,
-
10
青菜年糕汤 一周一篇,一期一会。以文会友,以友辅仁。 2020年8月23日 更新丢失、写偏、幻读:数据库事务从快照隔离到可序列化(二) 作者:青菜年糕汤...
-
5
技术内参 | 数据分析,如何解决精度丢失的问题? 神策小秘书 标...
-
8
在 JavaScript 中浮点数运算时经常出现 0.1+0.2=0.30000000000000004 这样的问题,除此之外还有一个不容忽视的大数危机(大数处理精度丢失)问题。之前也分享过这个问题,我在做个梳理分享给大家,
-
3
雪花算法ID到前端之后精度丢失问题 Posted on 2021-08-18 下面我把异常的现象给大家...
-
6
YOLOv8已至,精度大涨!教你如何在自定义数据集上训练它
-
6
如果你开发过涉及金额计算的 iOS app, 那么你很有可能经历过在使用浮点型数字时精度丢失的问题 让我们来...
-
3
javascript以64位双精度浮点数存储所有Number类型值,即计算机最多存储64位二进制数。 但是需要注意的是Number包含了我们常说的整形、浮点型,相比较于整形而言,会有一位存储小数点的偏移位,由于存储二进制时小数点的偏移量最大为52位,计算机存储的为二进制,而能...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK