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

这篇具有很好参考价值的文章主要介绍了解决BigDecimal序列化科学计数法前端展示问题(大坑)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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

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

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

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

public static String toJSONString(Object object, SerializerFeature... features) {
    return toJSONString(object, DEFAULT_GENERATE_FEATURE, features);
}

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

private static final SerializerFeature[] features = {
        SerializerFeature.WriteBigDecimalAsPlain};
public static String toString(Object data) {
        return JSON.toJSONString(data, features);
    }

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

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

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

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

public class BigDecimalConfig implements ObjectSerializer {
    public static final BigDecimalConfig instance = new BigDecimalConfig();
    @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;
        }
        out.writeString(((BigDecimal) object).stripTrailingZeros().toPlainString());
    }
}
public class JsonUtils {

    private static final SerializerFeature[] features = {
            SerializerFeature.WriteBigDecimalAsPlain	};
    
    private static final SerializeConfig serializeConfig  = SerializeConfig.globalInstance;

    static {
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);//打开autotype功能
        serializeConfig.put(BigDecimal.class, BigDecimalConfig.instance);//将BigDecimal转成字符串类型
    }

    /**
     * 生成JSON字符串
     */
    public static String toString(Object data) {
        return JSON.toJSONString(data, serializeConfig, features);// 需要传入自定义的配置
    }
}
1.2 fastJson对BigDecimal转成字符串类型返回(局部特定处理)

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

public class BigDecimalSerializer implements ObjectSerializer {

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

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

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

public class BigDecimalSerializer extends JsonSerializer<BigDecimal> {
    @Override
    public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider serializerProvider) throws IOException {
        gen.writeString(value.stripTrailingZeros().toPlainString());
    }
}
public class BigDecimalDeserializer extends JsonDeserializer<BigDecimal> {

    @Override
    public BigDecimal deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        return new BigDecimal(p.getValueAsString());
    }
}
@Configuration
public class JacksonConfig {

    @Bean
    public Jackson2ObjectMapperBuilder jacksonBuilder() {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.modules(new SimpleModule().addSerializer(BigDecimal.class, new BigDecimalSerializer())
                .addDeserializer(BigDecimal.class, new BigDecimalDeserializer()));
        return builder;
    }
}
2.1 jackson对BigDecimal转成字符串类型返回(全局处理)

自定义Jackson的JsonSerializer实现

public class BigDecimalToStringSerializer extends JsonSerializer<BigDecimal> {

    @Override
    public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeString(value.stripTrailingZeros().toPlainString());
    }
}

配置类中注册这个JsonSerializer

@Configuration
public class JacksonConfig {

//    @Bean
//    public Jackson2ObjectMapperBuilder jacksonBuilder() {
//        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
//        builder.modules(new SimpleModule().addSerializer(BigDecimal.class, new BigDecimalSerializer())
//                .addDeserializer(BigDecimal.class, new BigDecimalDeserializer()));
//        return builder;
//    }

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(BigDecimal.class, new BigDecimalToStringSerializer());
        objectMapper.registerModule(module);
        return objectMapper;
    }
}

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

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

@JsonSerialize(using = BigDecimalToStringSerializer.class)
private BigDecimal rate;

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

3、总结

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

到了这里,关于解决BigDecimal序列化科学计数法前端展示问题(大坑)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python中如何正确地使用科学计数法显示数字?

    Python中如何正确地使用科学计数法显示数字? 在数据分析和科学计算时,我们经常会遇到非常大或非常小的数字。默认情况下,Python会使用科学计数法来显示这些数字,例如1e+08和1e-06。虽然这种表示方法是精确的,但有时候在阅读和理解数据时可能不太直观。那么如何在P

    2024年02月14日
    浏览(81)
  • 日常踩坑:Java中double类型出现科学计数法问题

    背景:在与银行的项目对接中,近期客户反馈支付失败,错误信息是:“付款金额格式有问题”,经过日志分析,发现客户系统发送银行系统时,付款金额以科学计数法的形式传递参数。 重现: 经过测试发现,浮点数(double、float)当整数部分超过7位以上(不含7位),就会

    2024年02月16日
    浏览(44)
  • chatgpt赋能python:如何将Python中的数字转换为科学计数法

    在Python编程中,我们经常需要使用科学计数法来表示非常大或非常小的数字。在本文中,我们将介绍Python中将数字转换为科学计数法的几种方法。 Python可以使用字符串格式化操作符(%)来将数字转换为科学计数法。以下是一个例子: 这将输出数字 1.23e+09 。其中 %.2e 中的 %e 表

    2024年02月07日
    浏览(43)
  • C语言实例:输出八进制,十进制,十六进制,指定位数整数,带符号整数,科学计数法表示的整数

    直接使用printf函数输出整数即可,例如: 输出结果为: %d是printf函数的格式控制符,用于输出整数。在printf函数中,%d会被替换成一个整数变量的值。例如,printf(“%d”, num)中%d将被num的值替换,从而输出num的值作为整数。 使用printf函数的格式控制符可以输出指定位数的整数

    2024年02月08日
    浏览(55)
  • 使用序列化和反序列化函数archivedDataWithRootObject和unarchivedObjectOfClasses的使用和遇到问题及解决方案

    为何archiveRootObject和unarchiveObjectWithFile正常,而archivedDataWithRootObject和unarchivedObjectOfClasses一直报错。 [NSKeyedArchiver archiveRootObject:account toFile:path]; 和`c PPAccountModel *account = [NSKeyedUnarchiver unarchiveObjectWithFile:path]; 替换很简单,但是会一堆问题等着你解决,序列化和反序列全失败。

    2024年02月16日
    浏览(36)
  • Apache Shiro反序列化漏洞研究及解决方法

    前言 一个阳光明媚的午休,我正惬意的喝着茶听着音乐,享受美好生活的时候,客户的QQ头像闪动了,原以为是出了什么新需求临时需要调整,没想到客户反馈的是平台出现了严重漏洞,不敢小视,抄起电脑开弄 我根据客户给出的安全厂商反馈的问题,总结如下: 1,Shiro反

    2024年02月11日
    浏览(48)
  • SpringCache 框架使用以及序列化和缓存过期时间问题的解决

    目录 为什么使用Spring Cache 如何使用Spring Cache 1 加依赖 2 开启缓存 3 加缓存注解 序列化以及过期时间等问题 解决方案:自定义序列化方式 1.自定义序列化方式并设置白名单 2.配置并设置缓存的过期时间         缓存有诸多的好处,于是大家就摩拳擦掌准备给自己的应用加

    2024年02月15日
    浏览(40)
  • 解决一个JSON反序列化问题-空字符串变为空集合

    当我后端实体中定义如下: 如果前端传projectTypeId 是 null 或者 [] 都是没问题的。当前端传\\\"\\\" 则会报错。 报错如下: 意思是无法将空字符串强转为集合 前端把“” 变为null或者[]即可 (但是我所在这个项目,原先定义的是 private String projectTypeId; 前端传\\\"\\\" 也没毛病,但是后期更

    2024年01月25日
    浏览(49)
  • org.springframework.data.redis.serializer.SerializationException: Cannot serialize(解决redis存入对象序列化)

    在调用service 实现类时报出以上错误,原因是因为 spring会先将对象序列化,再存入redis进行缓存,而entity没有实现序列化接口,因此序列化出错,需要在对应的实体类中添加序列化即可(implements Serializable),如下:

    2024年02月14日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包