解决fastjsonLong型精度损失问题
解决fastjson Long型精度损失问题
问题
简括:1.@JSONField不⽣效2.全局配置精度损失不⽣效
直接问题:使⽤fastjson @JSONField⽆法处理前端获取long型数据精度损失问题,⽆法全局配置fastjson的long型精度损失问题。
底层剖析:将springBoot默认使⽤的json转换器(Jackson)替换为阿⾥fastjson时,实现WebMvcConfigurer并重写configureMessageConverters⽅法的配置并未⽣效。
解决⽅法:直接向spring容器注册新的Bean
1.创建HttpMessageConvertersConfig类,并使⽤@Configuration标记(经测使⽤@Component也可以),使spring识别;配置fastjson long转string
@Configuration
public class HttpMessageConvertersConfig {
@Bean
public HttpMessageConverters fastJsonHttpMessageConverters(){
FastJsonHttpMessageConverter fastConverter =new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig =new FastJsonConfig();
SerializeConfig serializeConfig = SerializeConfig.globalInstance;
serializeConfig.put(Long.class, LongToStringSerializer.instance);
serializeConfig.put(Long.TYPE, LongToStringSerializer.instance);
fastJsonConfig.setSerializeConfig(serializeConfig);
fastConverter.setFastJsonConfig(fastJsonConfig);
HttpMessageConverter<?> converter = fastConverter;
return new HttpMessageConverters(converter);
}
}
2.创建LongToStringSerializer类,实现ObjectSerializer接⼝,重写write⽅法
public class LongToStringSerializer implements ObjectSerializer {
public static final LongToStringSerializer instance =new LongToStringSerializer();
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType,int features)throws IOException {
SerializeWriter out = serializer.out;
if(object ==null){
out.writeNull();
return;
}
if(object instanceof Long){
String strVal = String();
out.writeString(strVal);
}
}
}
以上,为全局配置Long型转String,解决精度损失,如果想使⽤注解@JSONField,需要将注册的bean修改为以下配置(即去除long转string的配置内容),LongToStringSerializer类保留,在需要的Long型字段上加上@JSONField(serializeUsing = LongToStringSerializer.class)即可。
@Configuration
public class HttpMessageConvertersConfig {
fastjson常用方法@Bean
public HttpMessageConverters fastJsonHttpMessageConverters(){
FastJsonHttpMessageConverter fastConverter =new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig =new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
fastConverter.setFastJsonConfig(fastJsonConfig);
HttpMessageConverter<?> converter = fastConverter;
return new HttpMessageConverters(converter);
}
}
总结
之所以配置不⽣效、注解不能使⽤,根本问题其实都是因为Springboot默认会创建的MappingJackson2HttpMessageConverter转换器,⽽⽹上很多⽅法都是新建⼀个fastjson转换器,之后添加在列表后⾯,实际spring处理时,当有⼀个convert满⾜重写后,⽅法就直接返回了不会再交给下⼀个converter处理,因此之前⾃⼰写的convert并不能起作⽤。
所以我们应该直接修改springboot注册的MappingJackson2HttpMessageConverter 会使⽤到的ObjectMapper,或者⾃⼰注册⼀个MappingJackson2HttpMessageConverter bean,这样才能使⾃定义的转换器配置⽣效,本⽂即使⽤的是后者,前者的实现⽅法可以参考。如果你想以更精准的粒度来控制那些Long型进⾏转换(⽐如只转换id类别的Long属性),请参考的⽅法三,使⽤SerializeFilter。
他⼭之⽯
如有不当,欢迎指正