自定义序列化类 将ListLong转为String字符串解决雪花算法id精度丢失问题
众所周知,当后端使用Mybatis plus的雪花算法生成id时,会生成一个长度为19位的ID
然后当我们和前端小伙伴对接时,需要转为JSON给前端的js对象接收,此时接收Long类型的是number
然而number类型的长度只有16位!这就出现了精度丢失的问题
前端接收的 ---> 后端实际传的
1297873308628300000 ---> 1297873308628307970
那怎么办呢?
我们可以配置一个全局序列化以将Long类型在json序列化时转为String给前端
package com.aeotrade.provider.uac.config;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.springframework.boot.jackson.JsonComponent;
import org.springframework.context.annotation.Bean;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
@JsonComponent
public class JacksonConfig {
@Bean
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
/**
* 可配置项:
* 1.Include.Include.ALWAYS : 默认
* 2.Include.NON_DEFAULT : 默认值不序列化
* 3.Include.NON_EMPTY : 属性为 空("") 或者为 NULL 都不序列化
* 4.Include.NON_NULL : 属性为NULL 不序列化
**/
objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
/**
* 序列化时,将所有的long变成string
*/
SimpleModule module = new SimpleModule();
module.addSerializer(Long.class, ToStringSerializer.instance);
module.addSerializer(Long.TYPE, ToStringSerializer.instance);
objectMapper.registerModule(module);
return objectMapper;
}
}
然而这有个问题,他居然会将mybatis中一些分页的参数也转为了String类型,如total:“100”,这就不符合我们的要求了。
最简单的解决方法就是加入一个序列化的注解
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
但是,如果我是List< Long >类型直接加注解会将整个List转为String,得到的结果是[1,2,3],这显然不符合我们想要的1,2,3拼接字符串的结果。
于是我们可以自己自定义一个序列化器
/**
*@Description 自定义序列化器
*/
public class LongArray2StringSerialize extends JsonSerializer<List<Long>> {
@Override
public void serialize(List<Long> value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
StringBuffer sb = new StringBuffer();
for (Long str : value) {
if (sb.length() > 0) {
sb.append(",");
}
sb.append(str);
}
gen.writeString(sb.toString());
}
}
将序列化类指定为我们自定义的
@JsonSerialize(using = LongArray2StringSerialize.class)
private List<Long> ids;
大功告成!
ps:也可以在全局配置的时候,判断属性名后缀来避免序列化不需要的Long类型属性