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

打印 上一主题 下一主题

主题 1043|帖子 1043|积分 3129

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

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

   字段返回完整的数字,制止科学计数法
  我们看下JSON.toJSONString()的方法,我们可以看到,可以传进SerializerFeature的枚举
  1. public static String toJSONString(Object object, SerializerFeature... features) {
  2.     return toJSONString(object, DEFAULT_GENERATE_FEATURE, features);
  3. }
复制代码
以是,我们这边传进WriteBigDecimalAsPlain枚举,就可以将数字完整返回
  1. private static final SerializerFeature[] features = {
  2.         SerializerFeature.WriteBigDecimalAsPlain};
  3. public static String toString(Object data) {
  4.         return JSON.toJSONString(data, features);
  5.     }
复制代码
  PS: 大坑,我们可以发现这时间后端返回给前端是完整的数字,但是由于字段是数字范例,以是前端JS会把数字变成科学计数法展示,如下图展示,左边的数据是浏览器相应的数据,右边的数据是postman调用返回的数据,可以看到后端返回是没题目,但是由于前端JS的题目导致展示出现科学计数法。这时间,我们就需要考虑是不是返回给前端序列化成字符串范例返回。
  

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

   自定义序列化类实现ObjectSerializer接口重写内里write方法,并且把自定义序列化类放到fastJson序列化配置中
  1. public class BigDecimalConfig implements ObjectSerializer {
  2.     public static final BigDecimalConfig instance = new BigDecimalConfig();
  3.     @Override
  4.     public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType,
  5.                       int features) throws IOException {
  6.         SerializeWriter out = serializer.out;
  7.         if (object == null) {
  8.             out.writeNull();
  9.             return;
  10.         }
  11.         out.writeString(((BigDecimal) object).stripTrailingZeros().toPlainString());
  12.     }
  13. }
复制代码
  1. public class JsonUtils {
  2.     private static final SerializerFeature[] features = {
  3.             SerializerFeature.WriteBigDecimalAsPlain        };
  4.    
  5.     private static final SerializeConfig serializeConfig  = SerializeConfig.globalInstance;
  6.     static {
  7.         ParserConfig.getGlobalInstance().setAutoTypeSupport(true);//打开autotype功能
  8.         serializeConfig.put(BigDecimal.class, BigDecimalConfig.instance);//将BigDecimal转成字符串类型
  9.     }
  10.     /**
  11.      * 生成JSON字符串
  12.      */
  13.     public static String toString(Object data) {
  14.         return JSON.toJSONString(data, serializeConfig, features);// 需要传入自定义的配置
  15.     }
  16. }
复制代码
1.2 fastJson对BigDecimal转成字符串范例返回(局部特定处理)

   由于项目前端汗青题目,假如把BigDecimal范例的字段全部变成字符串范例,就有可能会引起其他题目,为了淘汰不须要的贫苦,特意搞了局部处理的方法,对某个字段做特殊处理。同样需要自定义序列化类实现ObjectSerializer接口重写内里write方法,然后在字段上加上序列化注解即可。@JSONField(serializeUsing = BigDecimalSerializer.class)
  1. public class BigDecimalSerializer implements ObjectSerializer {
  2.     @Override
  3.     public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
  4.         if (object == null) {
  5.             serializer.out.writeNull();
  6.             return;
  7.         }
  8.         if (object instanceof BigDecimal) {
  9.             // 将BigDecimal转换为字符串形式
  10.             serializer.write(((BigDecimal) object).stripTrailingZeros().toPlainString());
  11.         } else {
  12.             // 非BigDecimal类型,使用默认序列化方式
  13.             serializer.write(object);
  14.         }
  15.     }
  16. }
复制代码
  1. @JSONField(serializeUsing = BigDecimalSerializer.class)
  2. private BigDecimal logisticsPrice;//物流单价
复制代码
2、jackson对BigDecimal序列化和反序列化

   自定义序列化和反序列类,然后编写配置类
  1. public class BigDecimalSerializer extends JsonSerializer<BigDecimal> {
  2.     @Override
  3.     public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider serializerProvider) throws IOException {
  4.         gen.writeString(value.stripTrailingZeros().toPlainString());
  5.     }
  6. }
复制代码
  1. public class BigDecimalDeserializer extends JsonDeserializer<BigDecimal> {
  2.     @Override
  3.     public BigDecimal deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
  4.         return new BigDecimal(p.getValueAsString());
  5.     }
  6. }
复制代码
  1. @Configuration
  2. public class JacksonConfig {
  3.     @Bean
  4.     public Jackson2ObjectMapperBuilder jacksonBuilder() {
  5.         Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
  6.         builder.modules(new SimpleModule().addSerializer(BigDecimal.class, new BigDecimalSerializer())
  7.                 .addDeserializer(BigDecimal.class, new BigDecimalDeserializer()));
  8.         return builder;
  9.     }
  10. }
复制代码
2.1 jackson对BigDecimal转成字符串范例返回(全局处理)

自定义Jackson的JsonSerializer实现
  1. public class BigDecimalToStringSerializer extends JsonSerializer<BigDecimal> {
  2.     @Override
  3.     public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
  4.         gen.writeString(value.stripTrailingZeros().toPlainString());
  5.     }
  6. }
复制代码
配置类中注册这个JsonSerializer:
  1. @Configuration
  2. public class JacksonConfig {
  3. //    @Bean
  4. //    public Jackson2ObjectMapperBuilder jacksonBuilder() {
  5. //        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
  6. //        builder.modules(new SimpleModule().addSerializer(BigDecimal.class, new BigDecimalSerializer())
  7. //                .addDeserializer(BigDecimal.class, new BigDecimalDeserializer()));
  8. //        return builder;
  9. //    }
  10.     @Bean
  11.     public ObjectMapper objectMapper() {
  12.         ObjectMapper objectMapper = new ObjectMapper();
  13.         SimpleModule module = new SimpleModule();
  14.         module.addSerializer(BigDecimal.class, new BigDecimalToStringSerializer());
  15.         objectMapper.registerModule(module);
  16.         return objectMapper;
  17.     }
  18. }
复制代码
2.1 jackson对BigDecimal转成字符串范例返回(局部处理)
   第一步跟之前一样,自定义BigDecimalToStringSerializer序列化类,然后在某个字段上加上注解即可,@JsonSerialize(using = BigDecimalToStringSerializer.class)
  1. @JsonSerialize(using = BigDecimalToStringSerializer.class)
  2. private BigDecimal rate;
复制代码

3、总结

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

去皮卡多

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表