Java中BigDecimal序列化科學(xué)計數(shù)法前端展示問題踩坑實戰(zhàn)
前言:
在生產(chǎn)中出現(xiàn)一個問題,就是BigDecimal類型的字段在前端頁面展示變成科學(xué)計數(shù)法,通過排查,發(fā)現(xiàn)里面的坑還是挺多的,所以特意記錄下處理過程。Json序列化,不同項目中配置的都不一樣,有些項目是使用springboot里面自帶的jackson的,有些是使用fastjson處理,不同的序列化的處理方式也不一樣。
1、fastJson對BigDecimal序列化和反序列化
字段返回完整的數(shù)字,避免科學(xué)計數(shù)法
我們看下JSON.toJSONString()的方法,我們可以看到,可以傳進(jìn)SerializerFeature的枚舉
public static String toJSONString(Object object, SerializerFeature... features) { return toJSONString(object, DEFAULT_GENERATE_FEATURE, features); }
所以,我們這邊傳進(jìn)WriteBigDecimalAsPlain枚舉,就可以將數(shù)字完整返回
private static final SerializerFeature[] features = { SerializerFeature.WriteBigDecimalAsPlain}; public static String toString(Object data) { return JSON.toJSONString(data, features); }
PS: 大坑,我們可以發(fā)現(xiàn)這時候后端返回給前端是完整的數(shù)字,但是由于字段是數(shù)字類型,所以前端JS會把數(shù)字變成科學(xué)計數(shù)法展示,如下圖展示,左邊的數(shù)據(jù)是瀏覽器響應(yīng)的數(shù)據(jù),右邊的數(shù)據(jù)是postman調(diào)用返回的數(shù)據(jù),可以看到后端返回是沒問題,但是由于前端JS的問題導(dǎo)致展示出現(xiàn)科學(xué)計數(shù)法。這時候,我們就需要考慮是不是返回給前端序列化成字符串類型返回。
1.1 fastJson對BigDecimal轉(zhuǎn)成字符串類型返回(全局處理,推薦)
自定義序列化類實現(xiàn)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轉(zhuǎn)成字符串類型 } /** * 生成JSON字符串 */ public static String toString(Object data) { return JSON.toJSONString(data, serializeConfig, features);// 需要傳入自定義的配置 } }
1.2 fastJson對BigDecimal轉(zhuǎn)成字符串類型返回(局部特定處理)
由于項目前端歷史問題,如果把BigDecimal類型的字段全部變成字符串類型,就有可能會引起其他問題,為了減少不必要的麻煩,特意搞了局部處理的方法,對某個字段做特殊處理。同樣需要自定義序列化類實現(xiàn)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轉(zhuǎn)換為字符串形式 serializer.write(((BigDecimal) object).stripTrailingZeros().toPlainString()); } else { // 非BigDecimal類型,使用默認(rèn)序列化方式 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轉(zhuǎn)成字符串類型返回(全局處理)
自定義Jackson的JsonSerializer
實現(xiàn)
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.2 jackson對BigDecimal轉(zhuǎn)成字符串類型返回(局部處理)
第一步跟之前一樣,自定義BigDecimalToStringSerializer序列化類,然后在某個字段上加上注解即可,@JsonSerialize(using = BigDecimalToStringSerializer.class)
@JsonSerialize(using = BigDecimalToStringSerializer.class) private BigDecimal rate;
3、總結(jié)
BigDecimal里面的坑還是挺多的,頁面該類型字段科學(xué)計數(shù)法展示的話,我們要找清楚是什么原因,是后端返回有問題還是前端的問題,首先一定要保證后端返回的數(shù)據(jù)是正常完整的,不管是數(shù)字類型還是字符串類型。只要確保后端返回的數(shù)據(jù)是完整,剩下如果還有問題就可以協(xié)助前端一起排查處理了。
到此這篇關(guān)于Java中BigDecimal序列化科學(xué)計數(shù)法前端展示問題踩坑實戰(zhàn)的文章就介紹到這了,更多相關(guān)BigDecimal序列化科學(xué)計數(shù)法前端展示內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于jdk動態(tài)代理和cglib動態(tài)代理實現(xiàn)及區(qū)別說明
這篇文章主要介紹了基于jdk動態(tài)代理和cglib動態(tài)代理實現(xiàn)及區(qū)別說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-05-05詳解在SpringBoot應(yīng)用中獲取應(yīng)用上下文方法
本篇文章主要介紹了詳解在SpringBoot應(yīng)用中獲取應(yīng)用上下文方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-04-04自己動手實現(xiàn)mybatis動態(tài)sql的方法
下面小編就為大家分享一篇自己動手實現(xiàn)mybatis動態(tài)sql的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12mybatis typeAliases 給實體類起別名的方法
這篇文章主要介紹了mybatis typeAliases 給實體類起別名,本文給大家分享兩種用法,通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09