0
点赞
收藏
分享

微信扫一扫

解决fastjson Long型精度损失问题

三分梦_0bc3 2022-02-07 阅读 69

解决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 = object.toString();
            out.writeString(strVal);
        }
    }
}

以上,为全局配置Long型转String,解决精度损失,如果想使用注解@JSONField,需要将注册的bean修改为以下配置(即去除long转string的配置内容),LongToStringSerializer类保留,在需要的Long型字段上加上@JSONField(serializeUsing = LongToStringSerializer.class)即可。

@Configuration
public class HttpMessageConvertersConfig {

    @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,这样才能使自定义的转换器配置生效,本文即使用的是后者,前者的实现方法可以参考springboot2.0配置WebMvcConfigurer的configureMessageConverters方法不启用_小燃儿的博客-CSDN博客_configuremessageconverters。如果你想以更精准的粒度来控制那些Long型进行转换(比如只转换id类别的Long属性),请参考FastJson配置解决long类型在前端界面展示精度丢失问题_kangaroo的博客-CSDN博客_fastjson long的方法三,使用SerializeFilter。

他山之石

springboot2.0配置WebMvcConfigurer的configureMessageConverters方法不启用_小燃儿的博客-CSDN博客_configuremessageconverters

Springboot使用alibaba的fastJson,@JSONField不起作用的问题 - 穆晟铭 - 博客园 (cnblogs.com)

FastJson配置解决long类型在前端界面展示精度丢失问题_kangaroo的博客-CSDN博客_fastjson long

FastJson自定义全局序列化方式与源码解析_黄皮电耗子的博客-CSDN博客_fastjson全局自定义序列化

如有不当,欢迎指正

举报

相关推荐

0 条评论