0


解决BigDecimal序列化科学计数法前端展示问题(大坑)

解决BigDecimal序列化科学计数法前端展示问题(大坑)

前言:在生产中出现一个问题,就是BigDecimal类型的字段在前端页面展示变成科学计数法,通过排查,发现里面的坑还是挺多的,所以特意记录下处理过程。Json序列化,不同项目中配置的都不一样,有些项目是使用springboot里面自带的jackson的,有些是使用fastjson处理,不同的序列化的处理方式也不一样。

1、fastJson对BigDecimal序列化和反序列化

字段返回完整的数字,避免科学计数法

我们看下JSON.toJSONString()的方法,我们可以看到,可以传进SerializerFeature的枚举

publicstaticStringtoJSONString(Object object,SerializerFeature... features){returntoJSONString(object,DEFAULT_GENERATE_FEATURE, features);}

所以,我们这边传进WriteBigDecimalAsPlain枚举,就可以将数字完整返回

privatestaticfinalSerializerFeature[] features ={SerializerFeature.WriteBigDecimalAsPlain};publicstaticStringtoString(Object data){returnJSON.toJSONString(data, features);}

PS: 大坑,我们可以发现这时候后端返回给前端是完整的数字,但是由于字段是数字类型,所以前端JS会把数字变成科学计数法展示,如下图展示,左边的数据是浏览器响应的数据,右边的数据是postman调用返回的数据,可以看到后端返回是没问题,但是由于前端JS的问题导致展示出现科学计数法。这时候,我们就需要考虑是不是返回给前端序列化成字符串类型返回。

在这里插入图片描述

1.1 fastJson对BigDecimal转成字符串类型返回(全局处理,推荐)

自定义序列化类实现ObjectSerializer接口重写里面write方法,并且把自定义序列化类放到fastJson序列化配置中

publicclassBigDecimalConfigimplementsObjectSerializer{publicstaticfinalBigDecimalConfig instance =newBigDecimalConfig();@Overridepublicvoidwrite(JSONSerializer serializer,Object object,Object fieldName,Type fieldType,int features)throwsIOException{SerializeWriter out = serializer.out;if(object ==null){
            out.writeNull();return;}
        out.writeString(((BigDecimal) object).stripTrailingZeros().toPlainString());}}
publicclassJsonUtils{privatestaticfinalSerializerFeature[] features ={SerializerFeature.WriteBigDecimalAsPlain};privatestaticfinalSerializeConfig serializeConfig  =SerializeConfig.globalInstance;static{ParserConfig.getGlobalInstance().setAutoTypeSupport(true);//打开autotype功能
        serializeConfig.put(BigDecimal.class,BigDecimalConfig.instance);//将BigDecimal转成字符串类型}/**
     * 生成JSON字符串
     */publicstaticStringtoString(Object data){returnJSON.toJSONString(data, serializeConfig, features);// 需要传入自定义的配置}}
1.2 fastJson对BigDecimal转成字符串类型返回(局部特定处理)

由于项目前端历史问题,如果把BigDecimal类型的字段全部变成字符串类型,就有可能会引起其他问题,为了减少不必要的麻烦,特意搞了局部处理的方法,对某个字段做特殊处理。同样需要自定义序列化类实现ObjectSerializer接口重写里面write方法,然后在字段上加上序列化注解即可。@JSONField(serializeUsing = BigDecimalSerializer.class)

publicclassBigDecimalSerializerimplementsObjectSerializer{@Overridepublicvoidwrite(JSONSerializer serializer,Object object,Object fieldName,Type fieldType,int features)throwsIOException{if(object ==null){
            serializer.out.writeNull();return;}if(object instanceofBigDecimal){// 将BigDecimal转换为字符串形式
            serializer.write(((BigDecimal) object).stripTrailingZeros().toPlainString());}else{// 非BigDecimal类型,使用默认序列化方式
            serializer.write(object);}}}
@JSONField(serializeUsing =BigDecimalSerializer.class)privateBigDecimal logisticsPrice;//物流单价

2、jackson对BigDecimal序列化和反序列化

自定义序列化和反序列类,然后编写配置类

publicclassBigDecimalSerializerextendsJsonSerializer<BigDecimal>{@Overridepublicvoidserialize(BigDecimal value,JsonGenerator gen,SerializerProvider serializerProvider)throwsIOException{
        gen.writeString(value.stripTrailingZeros().toPlainString());}}
publicclassBigDecimalDeserializerextendsJsonDeserializer<BigDecimal>{@OverridepublicBigDecimaldeserialize(JsonParser p,DeserializationContext ctxt)throwsIOException{returnnewBigDecimal(p.getValueAsString());}}
@ConfigurationpublicclassJacksonConfig{@BeanpublicJackson2ObjectMapperBuilderjacksonBuilder(){Jackson2ObjectMapperBuilder builder =newJackson2ObjectMapperBuilder();
        builder.modules(newSimpleModule().addSerializer(BigDecimal.class,newBigDecimalSerializer()).addDeserializer(BigDecimal.class,newBigDecimalDeserializer()));return builder;}}
2.1 jackson对BigDecimal转成字符串类型返回(全局处理)

自定义Jackson的

JsonSerializer

实现

publicclassBigDecimalToStringSerializerextendsJsonSerializer<BigDecimal>{@Overridepublicvoidserialize(BigDecimal value,JsonGenerator gen,SerializerProvider serializers)throwsIOException{
        gen.writeString(value.stripTrailingZeros().toPlainString());}}

配置类中注册这个

JsonSerializer

@ConfigurationpublicclassJacksonConfig{//    @Bean//    public Jackson2ObjectMapperBuilder jacksonBuilder() {//        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();//        builder.modules(new SimpleModule().addSerializer(BigDecimal.class, new BigDecimalSerializer())//                .addDeserializer(BigDecimal.class, new BigDecimalDeserializer()));//        return builder;//    }@BeanpublicObjectMapperobjectMapper(){ObjectMapper objectMapper =newObjectMapper();SimpleModulemodule=newSimpleModule();module.addSerializer(BigDecimal.class,newBigDecimalToStringSerializer());
        objectMapper.registerModule(module);return objectMapper;}}

2.1 jackson对BigDecimal转成字符串类型返回(局部处理)

第一步跟之前一样,自定义BigDecimalToStringSerializer序列化类,然后在某个字段上加上注解即可,@JsonSerialize(using = BigDecimalToStringSerializer.class)

@JsonSerialize(using =BigDecimalToStringSerializer.class)privateBigDecimal rate;

在这里插入图片描述

3、总结

BigDecimal里面的坑还是挺多的,页面该类型字段科学计数法展示的话,我们要找清楚是什么原因,是后端返回有问题还是前端的问题,首先一定要保证后端返回的数据是正常完整的,不管是数字类型还是字符串类型。只要确保后端返回的数据是完整,剩下如果还有问题就可以协助前端一起排查处理了。

标签: java json

本文转载自: https://blog.csdn.net/qq798867485/article/details/135629998
版权归原作者 小lee编程 所有, 如有侵权,请联系我们删除。

“解决BigDecimal序列化科学计数法前端展示问题(大坑)”的评论:

还没有评论