記錄一次alibaba.fastjson,Double類型被轉換爲BigDecimal類型解決方法

記錄一次alibaba.fastjson,Double類型被轉換爲BigDecimal類型解決方法

問題描述

在一次開發過程當中遇到的一個關於FastJson的問題,我獲取到的數據對象是一種無規則的json字符串,需要轉換爲JsonObject對象後存入到MongDB裏面。但是在數據提交到MongoDB時發現,原本提交的Double類型保存到MongoDB的時候發現這個數據類型變成了String類型。因爲在mongo中使用了2dsphere,也出現了Can’t extract geo keys錯誤信息。

查詢問題

測試代碼

class TestEntity {
    private Double doubleVal;
    private Float floatVal;
    private String name;

    public Double getDoubleVal() {
        return doubleVal;
    }

    public void setDoubleVal(Double doubleVal) {
        this.doubleVal = doubleVal;
    }

    public Float getFloatVal() {
        return floatVal;
    }

    public void setFloatVal(Float floatVal) {
        this.floatVal = floatVal;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class JSONTest {
    public static void main(String[] args) {
        TestEntity testEntity = new TestEntity();
        testEntity.setDoubleVal(123.456001);
        testEntity.setFloatVal(123.45512F);
        testEntity.setName("測試FastJSON");
        String str = JSON.toJSON(testEntity).toString();
        JSONObject JB = JSON.parseObject(str);
        System.out.println("***** Test Start ******");
        System.out.println("doubleVal = " + JB.get("doubleVal"));
        System.out.println("floatVal = " + JB.get("floatVal"));
        System.out.println("name = " + JB.get("name"));
    }
}

開始debug代碼查找具體的問題出現在哪裏。經過的debug發現在使用alibaba的fastJson轉換的時候原數據裏面的Double類型被轉換成了BigDecimal。如下圖所示
debug信息
然後開始查看所調用的API文檔,最終定位到問題所在
在JSON類裏面的靜態代碼塊

static {
        int features = 0;
        int features = features | Feature.AutoCloseSource.getMask();
        features |= Feature.InternFieldNames.getMask();
        features |= Feature.UseBigDecimal.getMask();
        features |= Feature.AllowUnQuotedFieldNames.getMask();
        features |= Feature.AllowSingleQuotes.getMask();
        features |= Feature.AllowArbitraryCommas.getMask();
        features |= Feature.SortFeidFastMatch.getMask();
        features |= Feature.IgnoreNotMatch.getMask();
        DEFAULT_PARSER_FEATURE = features;
        features = 0;
        features = features | SerializerFeature.QuoteFieldNames.getMask();
        features |= SerializerFeature.SkipTransientField.getMask();
        features |= SerializerFeature.WriteEnumUsingName.getMask();
        features |= SerializerFeature.SortField.getMask();
        String featuresProperty = IOUtils.getStringProperty("fastjson.serializerFeatures.MapSortField");
        int mask = SerializerFeature.MapSortField.getMask();
        if("true".equals(featuresProperty)) {
            features |= mask;
        } else if("false".equals(featuresProperty)) {
            features &= ~mask;
        }

        DEFAULT_GENERATE_FEATURE = features;
        bytesLocal = new ThreadLocal();
        charsLocal = new ThreadLocal();
    }

在JSON類裏面的靜態代碼塊的第五行發現了 features |= Feature.UseBigDecimal.getMask();
通過對Feature類的查詢發現UseBigDecimal這個設置是用來使用BigDecimal來裝載數字的,否則使用Double。但是在JSON類中的靜態代碼塊中默認設置爲了True。

如何解決

出現問題就開始各種BD、Google問題。最終在全球最大的男性交流平臺的官方倉庫的Wiki中找到了答案
鏈接: github deserialize_disable_bigdecimal_cn.
按照Wiki的方法進行了下修改,解決了問題。

		TestEntity testEntity = new TestEntity();
        testEntity.setDoubleVal(123.456001);
        testEntity.setFloatVal(123.45512F);
        testEntity.setName("測試FastJSON");
        int disableDecimalFeature = JSON.DEFAULT_PARSER_FEATURE & ~Feature.UseBigDecimal.getMask();
        String str = JSON.toJSON(testEntity).toString();
        //JSONObject JB = JSON.parseObject(str);
        JSONObject JB = JSON.parseObject(str,JSONObject.class,disableDecimalFeature);
        System.out.println("***** Test Start ******");
        System.out.println("doubleVal = " + JB.get("doubleVal"));
        System.out.println("floatVal = " + JB.get("floatVal"));
        System.out.println("name = " + JB.get("name"));

debug信息
不過Float類型還是變成了Double類型,這個問題還沒有解決掉。

說實話還有一個坑就是在使用FastJson的時候有時候序列化以後變成無序的狀態,這個時候就要使用 Feature.OrderedField 這個特性,因爲默認是未開啓的

JSONObject JB = JSON.parseObject(str,JSONObject.class,disableDecimalFeature,Feature.OrderedField);

以上解決掉了所有問題了,感謝提供幫助的羣裏的小夥伴。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章