原创
Long和Long类型集合前端精度丢失解决办法锦集以及自定义JSON序列化方法
Long
和List<Long>
前端精度丢失解决办法锦集以及自定义JSON序列化方法
因为JS解析整型的时候是有最大值的,Number.MAX_SAFE_INTEGER
常量表示在 JavaScript 中最大的安全整数(maxinum safe integer)(253 - 1)
Number.MAX_SAFE_INTEGER // 9007199254740991
Math.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
@EnableWebMvc
public 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一般会有两种方式:
第一种:
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Bean
public HttpMessageConverters fastJsonHttpMessageConverter() {
return new HttpMessageConverters(new FastJsonHttpMessageConverter());
}
}
第二种:
@Configuration
public 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
@Configuration
public 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类型来接收
e.g.
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
*/
@Slf4j
public 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"
]
}
- 本文作者: lzhpo
- 本文链接: http://www.lzhpo.com/article/106
- 版权声明: 本文为本人原创文章,采用 CC BY 3.0 CN协议 ,可自由转载、引用,但需署名作者且注明文章出处。
正文到此结束
- 本文标签: Vue Java Spring Boot
- 版权声明: 本站原创文章,于2020年02月24日由lzhpo发布,转载请注明出处